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:
Now we will write this, using the route()
helper:
route('planets.show', ...)
— generates a URL for the route namedplanets.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
🚀 Chapter Summary:
You have mastered a structured and professional approach to organizing web routes in Laravel. You can now:
- Distinguish between
web
andapi
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.