Controllers keep route files small and give each part of the app a clear home.
A controller groups related request handlers in a class under app/Http/Controllers. Generate one with php artisan make:controller PostController; add --resource to stub the seven resource methods.
Wire it up with Route::get('/posts', [PostController::class, 'index']);. A controller with a single __invoke method can be routed directly: Route::post('/checkout', CheckoutController::class);.
Controller methods receive dependencies by type-hint. Laravel's service container injects them, along with route parameters:
public function update(Request $request, Post $post) { ... }The Illuminate\Http\Request object wraps everything about the request:
$request->input('title')reads from the query string or body (JSON too), with an optional default;$request->query('page')reads only the query string.$request->only(['title', 'body']),has('x'),filled('x'),boolean('remember'),integer('page').$request->file('avatar'),$request->user(),$request->ip(),$request->isMethod('post').
Return values become responses:
view('posts.index', ['posts' => $posts])renders a Blade template.redirect()->route('posts.show', $post)->with('status', 'Saved!')redirects with a flash message.- An array, a model or
response()->json($data, 201)produces JSON. abort(403)stops with an error page.
Keep controllers thin: validate, call a model or service, return a response.
Example
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index(Request $request)
{
$posts = Post::query()
->when($request->query('q'), fn ($q, $term) => $q->where('title', 'like', "%{$term}%"))
->latest()
->paginate(10);
return view('posts.index', ['posts' => $posts]);
}
public function show(Post $post)
{
return request()->wantsJson() ? $post : view('posts.show', compact('post'));
}
public function destroy(Post $post)
{
$post->delete();
return redirect()->route('posts.index')->with('status', 'Post deleted');
}
}Remember
- Route to [Controller::class, 'method'] or to an invokable controller
- Type-hint Request, models and services to have them injected
- Return a view, redirect, array/model (JSON) or response() object
Watch out for
- Putting business logic and queries for several features into one giant controller.