Resource Controllers

Resource Controllers for standard CRUD operations

graph TD A[Route::resource] --> B[Resource Controller] B --> C[index] B --> D[create] B --> E[store] B --> F[show] B --> G[edit] B --> H[update] B --> I[destroy] C --> J[GET /resource] D --> K[GET /resource/create] E --> L[POST /resource] F --> M[GET /resource/{id}] G --> N[GET /resource/{id}/edit] H --> O[PUT/PATCH /resource/{id}] I --> P[DELETE /resource/{id}]

Resource Controller is a Controller that manages all CRUD (Create, Read, Update, Delete) operations in one class. This pattern implements RESTful standard and makes code organized and maintainable.


Standard Resource Controller Methods:


  • <strong>index()</strong>: Display list of all resources (GET /resource)
  • <strong>create()</strong>: Display form to create new resource (GET /resource/create)
  • <strong>store()</strong>: Store new resource (POST /resource)
  • <strong>show()</strong>: Display specific resource (GET /resource/{id})
  • <strong>edit()</strong>: Display edit form (GET /resource/{id}/edit)
  • <strong>update()</strong>: Update resource (PUT/PATCH /resource/{id})
  • <strong>destroy()</strong>: Delete resource (DELETE /resource/{id})

Benefits of Resource Controllers:


  • Organized and standard code
  • RESTful conventions implementation
  • Automatic routes with <code>Route::resource()</code>
  • Reduced boilerplate code
  • Consistency in API design
  • Easier for testing

API Resource Controllers:


For API endpoints that don't need create() and edit() (because they don't have HTML forms), you can use Route::apiResource() which only creates index, store, show, update, destroy methods.

Examples

Creating Resource Controller

php artisan make:controller UserController --resource

// Or with model
php artisan make:controller UserController --resource --model=User

Artisan command to create Resource Controller.

Resource Route

// Full resource routes
Route::resource('users', UserController::class);

// Creates:
// GET    /users              index
// GET    /users/create       create
// POST   /users              store
// GET    /users/{user}       show
// GET    /users/{user}/edit  edit
// PUT    /users/{user}       update
// PATCH  /users/{user}       update
// DELETE /users/{user}       destroy

This one line creates all CRUD method routes.

API Resource Routes

// API resource (without create/edit)
Route::apiResource('users', UserController::class);

// Creates:
// GET    /users              index
// POST   /users              store
// GET    /users/{user}       show
// PUT    /users/{user}       update
// PATCH  /users/{user}       update
// DELETE /users/{user}       destroy

// Multiple API resources
Route::apiResources([
    'users' => UserController::class,
    'posts' => PostController::class,
]);

API resource routes that only create methods needed for API.

Partial Resource Routes

// Only specific methods
Route::resource('users', UserController::class)
    ->only(['index', 'show', 'store']);

// Exclude specific methods
Route::resource('users', UserController::class)
    ->except(['create', 'edit', 'destroy']);

// With middleware
Route::resource('users', UserController::class)
    ->middleware(['auth'])
    ->except(['index', 'show']);

Using only() and except() to limit methods.

Resource Controller Implementation

<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateUserRequest;

class UserController extends Controller
{
    public function index()
    {
        $users = User::paginate(15);
        return view('users.index', compact('users'));
    }
    
    public function create()
    {
        return view('users.create');
    }
    
    public function store(StoreUserRequest $request)
    {
        $user = User::create($request->validated());
        return redirect()->route('users.show', $user)
            ->with('success', 'User created');
    }
    
    public function show(User $user)
    {
        return view('users.show', compact('user'));
    }
    
    public function edit(User $user)
    {
        return view('users.edit', compact('user'));
    }
    
    public function update(UpdateUserRequest $request, User $user)
    {
        $user->update($request->validated());
        return redirect()->route('users.show', $user)
            ->with('success', 'User updated');
    }
    
    public function destroy(User $user)
    {
        $user->delete();
        return redirect()->route('users.index')
            ->with('success', 'User deleted');
    }
}

A complete Resource Controller with all methods.

Nested Resources

// Nested resource routes
Route::resource('users.posts', PostController::class);

// Creates:
// GET    /users/{user}/posts              index
// GET    /users/{user}/posts/create       create
// POST   /users/{user}/posts              store
// GET    /users/{user}/posts/{post}       show
// GET    /users/{user}/posts/{post}/edit edit
// PUT    /users/{user}/posts/{post}       update
// DELETE /users/{user}/posts/{post}       destroy

// In controller
public function index(User $user)
{
    $posts = $user->posts;
    return view('posts.index', compact('posts', 'user'));
}

Nested resources for relationships.

Resource Names

// Custom route names
Route::resource('users', UserController::class)
    ->names([
        'index' => 'users.list',
        'show' => 'users.view',
    ]);

// Or with prefix
Route::resource('users', UserController::class)
    ->names('admin.users');

// Usage
route('users.list');
route('users.view', $user);

Custom route names for resource routes.

Shallow Nesting

// Shallow nesting (avoid deep nesting)
Route::resource('users.posts', PostController::class)
    ->shallow();

// Creates:
// GET    /users/{user}/posts              index
// GET    /users/{user}/posts/create       create
// POST   /users/{user}/posts              store
// GET    /posts/{post}                    show (shallow)
// GET    /posts/{post}/edit               edit (shallow)
// PUT    /posts/{post}                    update (shallow)
// DELETE /posts/{post}                    destroy (shallow)

Shallow nesting to avoid very deep URLs.

Use Cases

  • Creating RESTful APIs
  • Managing CRUD operations for resources
  • Organizing code with standard structure
  • Creating admin panels
  • API endpoints with consistent structure
  • Nested resources for relationships

Common Mistakes

  • Using resource controller for non-CRUD operations
  • Not using Form Requests for validation
  • Putting business logic in controller
  • Not using route model binding
  • Forgetting middleware for protected routes
  • Using resource for everything which is over-engineering

Best Practices

  • Use resource controllers for CRUD operations
  • Use Form Requests for validation
  • Use route model binding
  • Use API resources for API endpoints
  • Use shallow nesting for nested resources
  • Put business logic in Service classes
  • Test resource controllers

Edge Cases

  • Nested resources with multiple levels
  • Resource routes with custom constraints
  • Resource controllers with soft deletes
  • API resources with different response formats
  • Resource routes with subdomain routing
  • Conditional resource methods

Performance Notes

  • Resource routes are faster with route caching
  • Using eager loading in index() is important
  • Pagination in index() for large datasets
  • Route model binding can improve performance

Security Notes

  • Always use middleware for protected routes
  • Use Form Requests for validation and authorization
  • Ensure destroy() method has authorization
  • Use route model binding for automatic 404

Interview Points

  • What is the difference between resource and apiResource?
  • When should you use resource controller?
  • What are nested resources and when are they used?
  • What is shallow nesting and why is it important?
  • How can you customize resource routes?
  • What are the benefits of using resource controllers?

Version Notes

  • Laravel 11.x: Improved performance in resource route resolution
  • Laravel 11.x: Better support for shallow nesting
  • Laravel 10.x: Improved API resource controllers
  • Laravel 9.x: Improved nested resource handling