Resource Controllers
Resource Controllers for standard CRUD operations
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