In one sentence

A route connects a URL (plus an HTTP method) to the code that should answer it.

๐Ÿ›Ž๏ธThink of routes as a hotel receptionist. A guest asks for โ€œroom 204โ€ (the URL), and the receptionist knows exactly who to send them to (your code). If nobody is assigned to that room, the guest gets a polite โ€œnot foundโ€ (404).

Why it matters

Every page starts with a route

๐Ÿšช

It's the front door

No route, no page. Every request into your app is matched against your route list first.

๐Ÿ—บ๏ธ

One map of your app

Open routes/web.php and you can see every URL your app answers, all in one place.

๐Ÿ”

Change URLs safely

Named routes let you rename a URL once, and every link updates automatically.

The big picture

What happens when someone visits /about

๐ŸŒBrowserGET /about
๐ŸงญRouterfinds a matching route
โš™๏ธYour codeclosure or controller
๐Ÿ“„ResponseHTML, JSON or redirect
The router reads the method + URL, picks the first matching route, runs its code and sends back whatever it returns.

Laravel keeps routes in the routes/ folder. You'll spend most of your time in two files:

FileUsed forComes with
routes/web.phpPages people visit in a browserSessions, cookies, CSRF protection
routes/api.phpJSON endpoints for apps & JS frontendsAutomatic /api prefix, stateless. Created by php artisan install:api
routes/console.phpCustom Artisan commands & schedulesNo HTTP at all
Step by step

Build your routing skills

Each step adds one idea. Try each snippet in a fresh Laravel project as you go.

  1. Your first route

    A route needs three things: the HTTP method (get), the URL (/hello), and the code to run. Here, the code is a closure (an unnamed function).

    
              <?php
    
              use Illuminate\Support\Facades\Route;
    
              Route::get('/hello', function () {
                  return 'Hello, Laravel! ๐Ÿ‘‹';
              });
            

    Run php artisan serve and visit http://127.0.0.1:8000/hello. Whatever the closure returns is sent back to the browser.

  2. Return a view instead of text

    Real pages are HTML, so you'll usually return a Blade view. view('about') loads resources/views/about.blade.php.

    
              Route::get('/about', function () {
                  return view('about', ['team' => 'Blueprint Crew']);
              });
    
              // Shortcut when there's no logic at all:
              Route::view('/contact', 'contact');
            

    The array passes data to the view. Inside Blade you can now write {{ $team }}.

  3. Capture parts of the URL with parameters

    Wrap a URL segment in {curly braces} and Laravel hands its value to your function. Add ? to make a parameter optional, and use a constraint to reject bad input.

    
              Route::get('/posts/{id}', function (string $id) {
                  return "Showing post #{$id}";
              })->whereNumber('id');        // /posts/abc โ†’ 404
    
              // Optional parameter with a default value
              Route::get('/greet/{name?}', function (string $name = 'friend') {
                  return "Hi, {$name}!";
              });
    
              Route::get('/users/{user}/posts/{post}', function (string $user, string $post) {
                  return "User {$user}, post {$post}";
              });
            
    โ„น๏ธ Coming later: route model binding

    Once you have models (Module 05), type-hint Post $post instead of string $id. Laravel then fetches the post from the database for you, or returns a 404 automatically.

  4. Give routes a name

    A named route is a nickname for a URL. You build links from the name, never by typing the path by hand.

    
              Route::get('/posts/{id}', function (string $id) {
                  // ...
              })->name('posts.show');
            
    
              <a href="{{ route('posts.show', ['id' => 42]) }}">Read post 42</a>
              {{-- renders: /posts/42 --}}
            
    
              return redirect()->route('posts.show', ['id' => 42]);
            
  5. Group routes that share settings

    When many routes share a prefix, middleware or controller, group them so you don't repeat yourself.

    
              use App\Http\Controllers\Admin\DashboardController;
    
              Route::prefix('admin')                 // URLs start with /admin
                  ->name('admin.')                   // names start with admin.
                  ->middleware('auth')               // must be logged in
                  ->group(function () {
                      Route::get('/dashboard', [DashboardController::class, 'index'])
                          ->name('dashboard');       // โ†’ admin.dashboard, /admin/dashboard
                      Route::get('/reports', [DashboardController::class, 'reports'])
                          ->name('reports');         // โ†’ admin.reports, /admin/reports
                  });
            

    Notice [DashboardController::class, 'index']. That's how a route points to a controller method instead of a closure. You'll build controllers in the next lesson.

  6. Match the right HTTP verb

    The same URL can do different things depending on the method. Browsers use GET to read and POST to submit forms. The others are used for updating and deleting.

    
              Route::get('/posts', ...);            // list posts
              Route::post('/posts', ...);           // save a new post
              Route::put('/posts/{id}', ...);       // replace a post
              Route::patch('/posts/{id}', ...);     // update part of a post
              Route::delete('/posts/{id}', ...);    // delete a post
    
              Route::match(['get', 'post'], '/search', ...);
              Route::any('/webhook', ...);
            
Common mistakes

Avoid this, do that

โŒ Avoid

          <a href="/posts/{{ $id }}">Read</a>
        

Hard-coded paths break silently when you change a URL, and you'll be hunting through dozens of templates.

โœ… Do

          <a href="{{ route('posts.show', $id) }}">Read</a>
        

Change the URL once in web.php, and every link that uses the route name keeps working.

โŒ Avoid

          Route::get('/posts/{id}', ...);
          Route::get('/posts/create', ...); // never reached!
        

/posts/create matches {id} first, with id = "create".

โœ… Do

          Route::get('/posts/create', ...);
          Route::get('/posts/{id}', ...)->whereNumber('id');
        

Put specific routes first, and constrain parameters so they only match what they should.

๐Ÿ’ก Pro tip: see every route at once

This prints a table of every route, its method, name and handler. It's the fastest way to debug a 404.


        php artisan route:list
        php artisan route:list --path=admin   # filter
      
๐Ÿ‹๏ธ Try it yourself

In a fresh Laravel project, build these routes:

  1. GET /: returns the text โ€œHomeโ€.
  2. GET /products/{id}: only accepts numbers, is named products.show, and returns โ€œProduct #IDโ€.
  3. A group with the prefix /shop containing /cart and /checkout, named shop.cart and shop.checkout.
  4. Run php artisan route:list and check that all four appear.
Recap

Key takeaways

Check yourself

Mini quiz