Master Laravel Controllers: From Basics to Advanced Resource Routing
This guide explains how to organize request handling with Laravel controllers, covering basic controller creation, namespace handling, single‑action controllers, middleware assignment, resource controllers with custom routes, dependency injection techniques, and route caching for production performance.
Controller Overview
Laravel controllers replace closure‑based route definitions by grouping related request‑handling logic into dedicated classes stored in app/Http/Controllers.
Basic Controller
A typical controller extends Laravel’s base Controller class, gaining helper methods such as middleware for attaching middleware to controller actions.
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show a user profile.
*
* @param int $id
* @return View
*/
public function show($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}Register the route:
Route::get('user/{id}', 'UserController@show');Tip: Controllers do not have to extend the base class, but without it you lose convenient methods like middleware , validate , and dispatch .
Controller & Namespace
When defining routes you only need the class name after App\Http\Controllers because RouteServiceProvider automatically prefixes the namespace. For deeper directories, specify the relative class name:
Route::get('foo', 'Photos\AdminController@method');Single‑Action Controllers
Define an __invoke method to handle a single behavior. The route does not need a method name:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class ShowProfile extends Controller
{
/**
* Show a given user profile.
*
* @param int $id
* @return View
*/
public function __invoke($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
} Route::get('user/{id}', 'ShowProfile');Generate it with Artisan:
php artisan make:controller ShowProfile --invokableController Middleware
Middleware can be attached directly in the route definition:
Route::get('profile', 'UserController@show')->middleware('auth');It is often more convenient to assign middleware inside the controller’s constructor, optionally limiting it to specific actions:
class UserController extends Controller
{
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}You can also register a closure as middleware for a single controller without creating a separate middleware class:
$this->middleware(function ($request, $next) {
// ...
return $next($request);
});Tip: Assigning middleware to only a subset of actions can indicate a controller is becoming too complex; consider splitting it into smaller controllers.
Resource Controllers
Laravel’s make:controller --resource command scaffolds a controller with the conventional CRUD methods. Register the controller with a single resource route declaration:
php artisan make:controller PhotoController --resource Route::resource('photos', 'PhotoController');The resource route creates multiple routes (index, create, store, show, edit, update, destroy). You can limit the generated actions with only or except:
Route::resource('photos', 'PhotoController')->only(['index', 'show']);
Route::resource('photos', 'PhotoController')->except(['create', 'store', 'update', 'destroy']);For API‑only controllers, use apiResource to omit the HTML‑related create and edit routes:
Route::apiResource('photos', 'PhotoController');Multiple API resources can be registered at once:
Route::apiResources([
'photos' => 'PhotoController',
'posts' => 'PostController',
]);Custom route names are possible via the names method:
Route::resource('photos', 'PhotoController')->names([
'create' => 'photos.build',
]);Override the default route‑parameter name with the parameters option:
Route::resource('users', 'AdminUserController')->parameters([
'users' => 'admin_user',
]);Localize the resource verbs (e.g., Spanish) in AppServiceProvider::boot:
use Illuminate\Support\Facades\Route;
public function boot()
{
Route::resourceVerbs([
'create' => 'crear',
'edit' => 'editar',
]);
}After localization, a resource route such as Route::resource('fotos', 'PhotoController') will generate URIs like /fotos/crear and /fotos/{foto}/editar.
Supplementary Resource Routes
Define additional routes before the resource declaration to avoid them being overridden:
Route::get('photos/popular', 'PhotoController@popular');
Route::resource('photos', 'PhotoController');Tip: Keep controllers focused; if you need many extra actions, split the logic into separate, smaller controllers.
Dependency Injection & Controllers
Constructor Injection
Laravel’s service container resolves controller dependencies automatically. Example injecting a repository:
<?php
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
class UserController extends Controller
{
protected $users;
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}Method Injection
Inject the request object or other services directly into controller methods. Route parameters can follow the injected services:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function store(Request $request)
{
$name = $request->name;
// ...
}
public function update(Request $request, $id)
{
// Update user $id using data from $request
}
}Route Caching
Note: Routes defined with closures cannot be cached. Convert them to controller routes before using the cache.
When the application uses only controller‑based routes, enable route caching to dramatically speed up route registration:
php artisan route:cacheAfter caching, every request loads the compiled route file. Add new routes by regenerating the cache. In production you should run the cache command only, and clear it with:
php artisan route:clearSigned-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Laravel Tech Community
Specializing in Laravel development, we continuously publish fresh content and grow alongside the elegant, stable Laravel framework.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
