Laravel Core

Laravel Route Resources

Sunday, November 3, 2024

// 3 min read

Laravel 11 Routing Controller
Laravel Route Resources

Route resources provide a convenient way to generate multiple route definitions for CRUD actions with a single line of code.

In this post, we will explore the basic setup and options that resources offer.

Resource Controller

First, you need to have a controller prepared with the CRUD methods. Luckily, Laravel has a command out of the box that generates a resource controller for you.

php artisan make:controller PostController --resource --model=Post

This command will generate the skeleton of the resource controller. While the --model option is recommended, it can be omitted. It is useful if you want to type-hint the model instance in the related methods.

For example, this is what it generates for the show method:

public function show(Post $post)
{
    //
}

If you do not specify the --model it generates the following:

public function show(string $id)
{
    //
}

You will need to customize the controller to fit your needs. Here is my simple PostController after editing each method.

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        $posts = Post::published()->latest()->paginate($request->input('limit', 10));

        return view('posts.index', compact('posts'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create()
    {
        return view('posts.create');
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required|string',
            'is_published' => 'boolean',
        ]);

        Post::create($request->all());

        return redirect()->route('posts.index');
    }

    /**
     * Display the specified resource.
     */
    public function show(Post $post)
    {
        return view('posts.show', compact('post'));
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(Post $post)
    {
        return view('posts.edit', compact('post'));
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, Post $post)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'content' => 'required|string',
            'is_published' => 'boolean',
        ]);

        $post->update($request->all());

        return redirect()->route('posts.index');
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(Post $post)
    {
        $post->delete();

        return redirect()->route('posts.index');
    }
}

Registering Route Resource

To register a route resource, define the resource route in your routes/web.php file like this:

Route::resource('posts', PostController::class)

This single line automatically generates the following routes:

Method

URI

Action

Description

GET

/posts

index

Display a list of posts

GET

/posts/create

create

Display a form to create a post

POST

/posts

store

Save a new post to database

GET

/posts/{post}

show

Display a specific post

GET

/posts/{post}/edit

edit

Show a form for editing a post

PUT/PATCH

/posts/{post}

update

Update a post in the database

DELETE

/posts/{post}

destroy

Delete a post from the database

Route Resource List

You notice that the resource also generates names for each route. The default syntax consists of a prefix followed by the method name: posts.index

Customizing Resource Routes

You may want to customize the resource routes to better fit the needs of your application.

Specifying Routes to Generate

Sometimes, you do not need the entire set of default actions. Instead, you can specify only the actions you want to use:

Route::resource('posts', PostController::class)->only(['index', 'show']);

The line above will generate only the index and show route definitions.

Alternatively, you can use the except method to list the routes you want to exclude from generation:

Route::resource('posts', PostController::class)->except(['delete']);

This will generate all routes except the delete route.

Customize Route Names

You can override the default route names. To do this, pass an array of new names for the specific routes you want to modify. Any routes not included in this array will keep their default names.

Route::resource('posts', PostController::class)->names([
    'index' => 'posts.list',
    'show' => 'posts.view',
    'create' => 'posts.add'
]);

Route Resource Names

Naming Resource Route Parameters

By default, resource route parameters are generated based on the singular version of the resource name (e.g., /posts becomes post). You can override this by using the parameters method.

Route::resource('profiles', ProfileController::class)->parameters(['profiles' => 'username']);

This will generate route definitions like: /profiles/{username}

Nested Resource Routes

Nested Resource Routes allow you to create resource routes for a child route. For example, if a post has multiple comments, and you need a controller to manage those comments. You may use "dot" notation in your route declarations:

Route::resource('posts.comments', PostCommentController::class);

This generates the following routes:

  • GET /posts/{post}/comments (index method)

  • GET /posts/{post}/comments/create (create method)

  • POST /posts/{post}/comments (store method)

  • GET /posts/{post}/comments/{comment} (show method)

  • GET /posts/{post}/comments/{comment}/edit (edit method)

  • PUT/PATCH /posts/{post}/comments/{comment} (update method)

  • DELETE /posts/{post}/comments/{comment} (destroy method)

And you can generate controller methods for nested routes using the controller generator command with the --parent option.

php artisan make:controller PostCommentController --resource --model=Comment --parent=Post

Which generates this controller class:

<?php

namespace App\Http\Controllers;

use App\Models\Comment;
use App\Models\Post;
use Illuminate\Http\Request;

class PostCommentController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Post $post)
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(Post $post)
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request, Post $post)
    {
        //
    }

    /**
     * Display the specified resource.
     */
    public function show(Post $post, Comment $comment)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(Post $post, Comment $comment)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, Post $post, Comment $comment)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(Post $post, Comment $comment)
    {
        //
    }
}

API Resource Routes

When developing an API, you exclude routes that present HTML templates such as the create and edit. For these routes, you can use the apiResource method.

Route::apiResource('posts', PostController::class);

This method generates only the following routes:

  • GET /posts (index method)

  • POST /posts (store method)

  • GET /posts/{post} (show method)

  • PUT/PATCH /posts/{post} (update method)

  • DELETE /posts/{post} (destroy method)

And you can use the controller generator command with the --api option to generate your resource API controller:

php artisan make:controller PostController --resource --model=Comment --api 

Here are the most important things you need to know about route resources. For more information, read my article about the basics of routing in Laravel and refer to the resource controller section of the official Laravel documentation.