Controllers and requests

Laravel · Essentials · 12 min

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.

Check yourself

  1. What does a controller method returning an Eloquent model produce?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: laravel.com/docs/12.x/controllers