Laravel Controllers Reference Guide
A Laravel controllers reference guide: organizing route logic into controller classes, resource controllers, and route model binding.
Laravel Reference
Basic controllers
A controller groups related request-handling logic into a single class instead of stacking closures in the routes file. Generate one with Artisan:
php artisan make:controller PostController
namespace App\Http\Controllers;
class PostController extends Controller
{
public function index()
{
return view('posts.index', [
'posts' => Post::latest()->get(),
]);
}
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
}
use App\Http\Controllers\PostController;
Route::get('/posts', [PostController::class, 'index']);
Route::get('/posts/{post}', [PostController::class, 'show']);
Route model binding
When a route or controller method's type-hinted parameter name matches a route segment, Laravel automatically resolves the model instance (or throws a 404 if it isn't found) — no manual findOrFail() needed.
Route::get('/posts/{post}', [PostController::class, 'show']);
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
// Bind by a different column, e.g. a slug
Route::get('/posts/{post:slug}', [PostController::class, 'show']);
Single action (invokable) controllers
For a controller that only ever does one thing, define __invoke() instead of a named method, and omit the method when registering the route.
php artisan make:controller ProvisionServer --invokable
class ProvisionServer extends Controller
{
public function __invoke(Request $request)
{
// ...
}
}
Route::post('/servers', ProvisionServer::class);
Resource controllers
Generate a controller with stub methods for the seven conventional CRUD actions:
php artisan make:controller PostController --resource
php artisan make:controller PostController --resource --model=Post
Route::resource('posts', PostController::class);
// Only some of the seven actions
Route::resource('posts', PostController::class)->only(['index', 'show']);
Route::resource('posts', PostController::class)->except(['destroy']);
// A read-only, JSON-only version for an API
Route::apiResource('posts', PostController::class);
| Verb | URI | Action | Route name |
|---|---|---|---|
| GET | /posts | index | posts.index |
| GET | /posts/create | create | posts.create |
| POST | /posts | store | posts.store |
| GET | /posts/{post} | show | posts.show |
| GET | /posts/{post}/edit | edit | posts.edit |
| PUT/PATCH | /posts/{post} | update | posts.update |
| DELETE | /posts/{post} | destroy | posts.destroy |
Dependency injection
The service container automatically resolves type-hinted class dependencies in both constructors and individual methods (in addition to any route-bound models).
class PostController extends Controller
{
public function __construct(
protected PostRepository $posts,
) {}
public function store(StorePostRequest $request)
{
$post = $this->posts->create($request->validated());
return redirect()->route('posts.show', $post);
}
}
Middleware
Attach middleware to a controller's routes either in the route definition or, in Laravel 11+, via a static middleware() method on the controller itself.
Route::get('/dashboard', [DashboardController::class, 'index'])
->middleware('auth');
class PostController extends Controller implements HasMiddleware
{
public static function middleware(): array
{
return [
'auth',
new Middleware('log', only: ['store']),
];
}
}