Skip to content

Chapter 5.5: Routing for Web Pages

Study time: 40 minutes


1. routes/web.php vs routes/api.php: Two Different Control Panels

It is important to reinforce the fundamental difference once again:

Characteristic routes/web.php (Web Panel) routes/api.php (API Panel)
Main Task Displaying HTML pages, handling forms Providing data in JSON format for other applications
State Stateful — uses sessions and cookies Stateless — each request is independent
Default Middleware web (includes sessions, CSRF protection, cookie encryption) api (includes "throttling" — request rate limiting)
URL Prefix None (the root of your site) /api/ (configured in RouteServiceProvider)
Authentication Usually via sessions (Login/Password) Usually via tokens (Sanctum, Passport)

We are working with routes/web.php to build an interface for a live person.


2. Resource Routes for the Web

Similar to Route::apiResource, there is Route::resource for the web. It creates routes for the full CRUD cycle, including pages for displaying creation and editing forms.

Let's create a full set of routes for managing our planets through the web interface.

Step 1: Create a route in routes/web.php

Comment out or delete the old routes for /planets and replace them with a single line:

use App\Http\Controllers\Web\PlanetPageController;

// Route::get('/planets', [PlanetPageController::class, 'index']);
// Route::get('/planets/{planet}', [PlanetPageController::class, 'show']);

Route::resource('planets', PlanetPageController::class);

Step 2: See what was created Execute the command php artisan route:list --except-vendor in the terminal:

+--------+-----------+------------------------+------------------+-------------------------------------------------+------------+
| Method | URI       | Name                   | Action           | Middleware                                      |
+--------+-----------+------------------------+------------------+-------------------------------------------------+------------+
| GET|HEAD | planets                | planets.index          | ...\PlanetPageController@index                    | web        |
| POST   | planets                | planets.store          | ...\PlanetPageController@store                    | web        |
| GET|HEAD | planets/create         | planets.create         | ...\PlanetPageController@create                   | web        |
| GET|HEAD | planets/{planet}       | planets.show           | ...\PlanetPageController@show                     | web        |
| PUT|PATCH | planets/{planet}       | planets.update         | ...\PlanetPageController@update                   | web        |
| DELETE | planets/{planet}       | planets.destroy        | ...\PlanetPageController@destroy                  | web        |
| GET|HEAD | planets/{planet}/edit  | planets.edit           | ...\PlanetPageController@edit                     | web        |
+--------+-----------+------------------------+------------------+-------------------------------------------------+------------+

Route::resource created 7 routes for us, including:

  • planets.create (GET /planets/create): page with a creation form.
  • planets.store (POST /planets): processing this form.
  • planets.edit (GET /planets/{planet}/edit): page with an editing form.
  • planets.update (PUT/PATCH /planets/{planet}): processing the editing form.
  • planets.destroy (DELETE /planets/{planet}): deleting a resource.

3. Named Routes: Convenient "Space Coordinates"

Pay attention to the Name column. Laravel has automatically assigned a unique name to each route (e.g., planets.index). Using names instead of hard-coded URLs is a best practice.

Why? If you decide to change the URL from /planets to /worlds, you won't have to search and change all the links in your templates. You just change it in one place — in the routes file, and the names remain the same.

Example of use in Blade:

We used to write this:

<a href="/planets/{{ $planet->id }}">Learn more &rarr;</a>

Now we will write this, using the route() helper:

<a href="{{ route('planets.show', ['planet' => $planet->id]) }}">Learn more &rarr;</a>

  • route('planets.show', ...) — generates a URL for the route named planets.show.
  • ['planet' => $planet->id] — passes the necessary parameters to the URL. Laravel will substitute the ID into {planet} itself. You can even pass the entire model: ['planet' => $planet].

4. Implementing the Missing Methods in the Controller

Route::resource created the routes, but we need to create the corresponding methods in PlanetPageController ourselves.

Open app/Http/Controllers/Web/PlanetPageController.php and add them.

<?php
use Illuminate\Http\Request; // <-- Add

class PlanetPageController extends Controller
{
    // We already have index() and show()

    /**
     * Shows the form for creating a new planet.
     */
    public function create()
    {
        return view('planets.create'); // Just return the view with the form
    }

    /**
     * Stores a new planet in the database.
     */
    public function store(Request $request)
    {
        // Validate the data from the form
        $validated = $request->validate([
            'name' => 'required|string|max:255|unique:planets',
            'solar_system' => 'required|string|max:100',
            // ... other rules
        ]);

        Planet::create($validated);

        // Redirect the user to the list page with a success message
        return redirect()->route('planets.index')->with('success', 'Planet successfully created!');
    }

    /**
     * Shows the form for editing a planet.
     */
    public function edit(Planet $planet)
    {
        return view('planets.edit', ['planet' => $planet]);
    }

    /**
     * Updates the planet's data in the database.
     */
    public function update(Request $request, Planet $planet)
    {
        $validated = $request->validate([
            'name' => 'required|string|max:255|unique:planets,name,' . $planet->id,
            'solar_system' => 'required|string|max:100',
        ]);

        $planet->update($validated);

        return redirect()->route('planets.show', $planet)->with('success', 'Planet data updated!');
    }

    /**
     * Deletes a planet.
     */
    public function destroy(Planet $planet)
    {
        $planet->delete();

        return redirect()->route('planets.index')->with('success', 'Planet decommissioned.');
    }
}
  • redirect()->route(...) — redirects the user to another named route.
  • ->with('success', '...') — adds a "flash message" to the session, which will be available on the next page exactly once. We can display it in our Blade template.

5. Grouping Routes

If you have many routes with common characteristics (e.g., they are all for the admin panel and should have the /admin prefix and special middleware), you can group them.

<?php
Route::middleware(['auth', 'admin'])->prefix('admin')->name('admin.')->group(function () {
    // All routes within this group will have:
    // 1. 'auth' and 'admin' middleware
    // 2. The '/admin' URL prefix (e.g., /admin/planets)
    // 3. The 'admin.' name prefix (e.g., admin.planets.index)

    Route::resource('planets', PlanetPageController::class);
    // Route::get('/dashboard', ...)->name('dashboard'); // -> admin.dashboard
});

Quiz to Reinforce

1. Which command in `routes/web.php` will create a full set of CRUD routes for a web interface?

2. What is the main advantage of using named routes?

3. Which route will be generated for the `create()` method in `Route::resource('articles', ...)`?

4. What does the code `redirect()->route('home')->with('status', 'OK')` do?

5. What is `Route::prefix('dashboard')` used for?


🚀 Chapter Summary:

You have mastered a structured and professional approach to organizing web routes in Laravel. You can now:

  • Distinguish between web and api routes and their purposes.
  • Use Route::resource to quickly generate standard CRUD routes.
  • Apply named routes to create flexible and maintainable code.
  • Create full CRUD operations in a controller with validation and redirects.
  • Group routes to apply common rules.

The navigation system of your "ship" is now fault-tolerant and ready for expansion. In the final chapter of this section, we will combine all the knowledge we have gained and display the planet data, obtained via Fetch, on our Blade page.