Routing

Laravel · Essentials · 12 min

Routes are the front door of every Laravel app and determine how URLs reach your controllers.

Routes live in routes/web.php (with sessions, cookies and CSRF protection) and routes/api.php (stateless, prefixed with /api). The simplest route returns a value directly:

Route::get('/hello', fn () => 'Hello');

There are methods for each verb: get, post, put, patch, delete, plus match and any. Strings are sent as HTML, arrays and models as JSON.

  • Parameters: /posts/{id} passes $id to the handler; {slug?} is optional and needs a default. Constrain with ->whereNumber('id').
  • Named routes: ->name('posts.show'), then generate URLs with route('posts.show', ['id' => 5]). Never hard-code URLs in views.
  • Groups share attributes: Route::prefix('admin')->middleware('auth')->group(function () { ... }).
  • Resource routes: Route::resource('photos', PhotoController::class) registers the seven conventional routes (index, create, store, show, edit, update, destroy); apiResource skips the two HTML form routes.

Route model binding is a big convenience: type-hint a model and name the parameter accordingly, and Laravel fetches it or returns 404:

Route::get('/users/{user}', fn (User $user) => $user);

Use {post:slug} to bind by another column. php artisan route:list shows every registered route.

Example

<?php
// routes/web.php
use App\Http\Controllers\PhotoController;
use App\Models\Post;
use Illuminate\Support\Facades\Route;

Route::get('/', fn () => view('welcome'))->name('home');

Route::get('/greet/{name?}', fn (string $name = 'guest') => "Hello, $name")
    ->where('name', '[A-Za-z]+');

// /posts/my-first-post -> Post found by slug, or 404
Route::get('/posts/{post:slug}', fn (Post $post) => $post)->name('posts.show');

Route::resource('photos', PhotoController::class);
// GET /photos, GET /photos/create, POST /photos, GET /photos/{photo},
// GET /photos/{photo}/edit, PUT/PATCH /photos/{photo}, DELETE /photos/{photo}

Route::prefix('admin')->middleware('auth')->name('admin.')->group(function () {
    Route::get('/stats', fn () => ['users' => 42])->name('stats');   // admin.stats
});

// route('posts.show', $post) -> https://example.test/posts/my-first-post

Remember

  • Each HTTP verb has a Route method; return strings, views or JSON
  • Name routes and build URLs with route()
  • Type-hinted model parameters are fetched automatically (404 if missing)

Watch out for

  • Hard-coding URLs in views instead of using named routes, which breaks when paths change.

Check yourself

  1. What does Route::get('/users/{user}', fn (User $user) => $user) do for /users/999 if no such user exists?

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

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