Bitcoscript
Routing & Controllers

Resource Controllers: CRUD in One Line

Resource Controllers: CRUD in One Line

In this article, we'll walk through what resource controllers are, how to generate one, and how the seven standard CRUD methods map to their corresponding routes.

1 views

Introduction

If you've ever built a feature that needs the standard set of operations — listing items, showing a single item, creating a new one, editing it, updating it, and deleting it — you've probably noticed a pattern: these six or seven actions show up over and over again, for almost every resource in almost every application. Posts, products, users, comments — the CRUD (Create, Read, Update, Delete) pattern repeats constantly.

Laravel recognizes this pattern and gives you a powerful shortcut: resource controllers. With just one command to generate the controller and one line to register the routes, you get a fully wired-up CRUD structure, following RESTful conventions, without manually defining seven separate routes every single time.

In this article, we'll walk through what resource controllers are, how to generate one, and how the seven standard CRUD methods map to their corresponding routes.

What is a Resource Controller?

A resource controller is a controller pre-structured with methods that correspond to the standard CRUD operations. Instead of manually creating each method and route yourself, Laravel generates them all at once, following a predictable, RESTful naming convention.

Generating a Resource Controller

php

php artisan make:controller PostController --resource

This creates a controller with seven pre-defined (empty) methods:

php

class PostController extends Controller
{
    public function index() { }
    public function create() { }
    public function store(Request $request) { }
    public function show($id) { }
    public function edit($id) { }
    public function update(Request $request, $id) { }
    public function destroy($id) { }
}

Registering Resource Routes

Instead of defining seven separate Route::get(), Route::post(), etc. calls, you register all of them with a single line:

php

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

This one line automatically creates all seven routes, complete with proper HTTP methods, URLs, and route names.

Understanding the Seven CRUD Methods

Here's what each method is responsible for, along with the route it maps to:

Method

HTTP Verb

URL

Purpose

Route Name

index

GET

/posts

Display a list of all posts

posts.index

create

GET

/posts/create

Show a form to create a new post

posts.create

store

POST

/posts

Save a newly created post

posts.store

show

GET

/posts/{post}

Display a single post

posts.show

edit

GET

/posts/{post}/edit

Show a form to edit an existing post

posts.edit

update

PUT/PATCH

/posts/{post}

Update an existing post

posts.update

destroy

DELETE

/posts/{post}

Delete an existing post

posts.destroy

Every one of these routes is automatically named following the resource.action pattern, so you can immediately use them with the route() helper, as covered in our earlier article on named routes.

Filling In the Logic

Once the structure exists, you fill in each method with actual logic. Here's a simplified example using an Eloquent model (which we'll cover in more depth in a later article):

php

public function index()
{
    $posts = Post::all();
    return view('posts.index', ['posts' => $posts]);
}

public function store(Request $request)
{
    Post::create($request->all());
    return redirect()->route('posts.index');
}

public function show($id)
{
    $post = Post::findOrFail($id);
    return view('posts.show', ['post' => $post]);
}

public function destroy($id)
{
    Post::findOrFail($id)->delete();
    return redirect()->route('posts.index');
}

Generating Only the Routes You Need

Not every resource needs all seven routes. For example, a simple resource might only need index, show, store, and destroy, without full editing support. Laravel lets you limit which routes get registered:

php

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

Or, alternatively, exclude specific ones:

php

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

The except() approach is especially common for API-focused resources, since create and edit are meant to return HTML forms — something an API typically doesn't need.

API Resource Controllers

If you're building an API rather than a traditional web application, you likely don't need the create and edit methods at all, since those exist only to display HTML forms. Laravel provides a dedicated shortcut for this case:

php

php artisan make:controller PostController --api

php

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

This automatically registers only the five routes relevant to an API: index, store, show, update, and destroy.

Tips for Using Resource Controllers

  1. Default to resource controllers whenever you're building standard CRUD functionality — it saves time and keeps your routes consistent with Laravel's conventions.

  2. Use --api and apiResource() when building a JSON API, to avoid generating unnecessary create and edit methods.

  3. Use only() or except() to trim down routes for resources that don't need the full CRUD set, rather than manually deleting generated routes later.

  4. Run php artisan route:list after registering a resource route to see the exact URLs, methods, and names it created.

  5. Keep resource controller methods focused on their intended purpose — resist the temptation to add unrelated custom logic into index or show, and create separate custom routes/methods instead.

FAQ About Resource Controllers

1. Do I have to implement all seven methods, even if I don't use some of them? No. You can leave methods empty (Laravel won't complain), but it's cleaner to use only() or except() on the route definition to avoid registering routes for methods you don't plan to implement.

2. What's the difference between Route::resource() and Route::apiResource()? Route::resource() registers all seven CRUD routes, including create and edit (which return HTML forms), while Route::apiResource() registers only the five routes relevant to a JSON API, skipping form-related routes entirely.

3. Can I add custom routes alongside a resource route? Yes, absolutely. You can define additional custom routes for the same controller before or after the Route::resource() line, for actions that don't fit the standard CRUD pattern.

4. Why does my show route show a 404 even though the ID exists? This is often related to route model binding or a mismatch between how you're querying the database inside the method. Double check that you're using findOrFail() or Eloquent correctly, which we'll explore further in the article on route model binding.

5. Can I rename the routes generated by a resource controller? Yes, using the ->names() method, you can customize the route names if the defaults (like posts.index) don't fit your naming conventions.

6. Is Route::resource() slower than defining routes manually? No, there's no meaningful performance difference. It's purely a convenience for writing less code — Laravel compiles the routes the same way either way.

Conclusion

Resource controllers are one of Laravel's most beloved productivity features, turning what would normally be seven separate route definitions and a hand-built controller into a single command and a single line of route registration. Once you get comfortable with the CRUD naming convention, working with resources becomes fast and predictable across every project.

In the next article, we'll explore middleware — what it is, how it fits into the request lifecycle, and how to build your own custom middleware for tasks like authentication checks or request logging.

Found this helpful? Share it!

Tweet

Comments

Leave a Comment