Unit 3 - Notes
Unit 3: Controllers, Blade and Advanced Routing
1. Basic Controllers
In the Model-View-Controller (MVC) architecture, the Controller acts as the traffic cop. It handles incoming HTTP requests, retrieves necessary data from the Model, and passes that data to the View for presentation.
Creating Controllers
Controllers are typically stored in the app/Http/Controllers directory. They are PHP classes that extend the base Controller class provided by the framework.
Generation via Command Line (Artisan):
To create a controller, utilize the command line interface:
php artisan make:controller UserController
Basic Class Structure:
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Show the profile for a given user.
*/
public function show($id)
{
return view('user.profile', [
'user' => User::findOrFail($id)
]);
}
}
Controller Routing
To make a controller method accessible, it must be defined in the routing file (typically routes/web.php or routes/api.php).
Basic syntax:
use App\Http\Controllers\UserController;
// Route::get('url-path', [ControllerClass::class, 'methodName']);
Route::get('/user/{id}', [UserController::class, 'show']);
Controller Middleware
Middleware provides a mechanism for inspecting and filtering HTTP requests entering your application (e.g., ensuring a user is logged in). Middleware can be assigned to controller routes in two ways:
-
In the Route definition:
PHPRoute::get('profile', [UserController::class, 'show'])->middleware('auth'); -
In the Controller Constructor:
This allows for more granular control, such as applying middleware to specific methods.
PHPclass UserController extends Controller { public function __construct() { // Apply to all methods $this->middleware('auth'); // Apply only to specific methods $this->middleware('log')->only('index'); // Apply to all except specific methods $this->middleware('subscribed')->except('store'); } }
Restful Resource Controllers
Resource routing assigns typical "CRUD" (Create, Read, Update, Delete) routes to a controller with a single line of code.
Creating a Resource Controller:
php artisan make:controller PhotoController --resource
Registering the Route:
Route::resource('photos', PhotoController::class);
The 7 Standard Actions:
This single route declaration creates multiple routes to handle a variety of actions:
| Verb | URI | Action | Route Name | Purpose |
|---|---|---|---|---|
| GET | /photos |
index | photos.index | Display a list of photos. |
| GET | /photos/create |
create | photos.create | Show form to create a new photo. |
| POST | /photos |
store | photos.store | Store a new photo in DB. |
| GET | /photos/{photo} |
show | photos.show | Display a specific photo. |
| GET | /photos/{photo}/edit |
edit | photos.edit | Show form to edit a photo. |
| PUT/PATCH | /photos/{photo} |
update | photos.update | Update a specific photo in DB. |
| DELETE | /photos/{photo} |
destroy | photos.destroy | Delete a specific photo. |
2. Blade Templating Engine
Blade is a powerful templating engine. Unlike other PHP templating engines, Blade does not restrict the use of plain PHP code in views. All Blade views are compiled into plain PHP code and cached until they are modified.
Creating Templates
Blade view files use the .blade.php file extension and are typically stored in the resources/views directory.
PHP Output
To display data passed to the view, Blade uses "Mustache" syntax.
1. Displaying Data (Escaped):
This automatically runs PHP's htmlspecialchars function to prevent XSS attacks.
Hello, {{ $name }}.
2. Displaying Unescaped Data:
If you need to output HTML explicitly (use with caution):
Hello, {!! $name !!}.
3. Rendering JSON:
Blade provides a directive to render variables as JSON for JavaScript usage.
<script>
var appData = @json($array);
</script>
Control Structures
Blade provides convenient shortcuts for common PHP control structures.
Conditionals:
@if (count($records) === 1)
I have one record!
@elseif (count($records) > 1)
I have multiple records!
@else
I don't have any records!
@endif
@unless (Auth::check())
You are not signed in.
@endunless
Loops:
@foreach ($users as $user)
<p>This is user {{ $user->id }}</p>
@endforeach
@for ($i = 0; $i < 10; $i++)
The current value is {{ $i }}
@endfor
@while (true)
<p>I'm looping forever.</p>
@endwhile
Templates Inheritance
The primary benefit of Blade is template inheritance, allowing you to define a master "layout" and have child views extend it.
The Layout (resources/views/layouts/app.blade.php):
Defines the structure of the HTML page.
<html>
<head>
<title>App Name - @yield('title')</title>
</head>
<body>
<div class="sidebar">
@section('sidebar')
This is the master sidebar.
@show
</div>
<div class="container">
@yield('content')
</div>
</body>
</html>
The Child Page:
Extends the layout and injects content into the sections.
@extends('layouts.app')
@section('title', 'Page Title')
@section('sidebar')
@parent
<p>This is appended to the master sidebar.</p>
@endsection
@section('content')
<p>This is my body content.</p>
@endsection
@yield: Used to display the contents of a given section.@section: Defines a section of content.@parent: Appends content to the layout's sidebar rather than overwriting it.
3. Advanced Routing
Named Routes
Named routes allow the generation of URLs or redirects for specific routes. This decouples the route logic from the actual URI, meaning if you change the URI path, you don't have to update every link in your application.
Definition:
Route::get('/user/profile', [UserProfileController::class, 'show'])->name('profile');
Usage:
// Generating URLs
$url = route('profile');
// Generating Redirects
return redirect()->route('profile');
Secure Routes
While modern frameworks generally handle protocol detection automatically, you can force routes to be served over HTTPS. This is often handled at the web server level (Nginx/Apache) or via Middleware (ForceHttps), but can be conceptually grouped in routing.
Parameter Constraints
You can constrain the format of your route parameters using the where method on a route instance. This uses Regular Expressions.
Examples:
// ID must be a number
Route::get('/user/{id}', function ($id) {
// ...
})->where('id', '[0-9]+');
// Name must be alphabetic
Route::get('/user/{name}', function ($name) {
// ...
})->where('name', '[A-Za-z]+');
// Multiple constraints
Route::get('/user/{id}/{name}', function ($id, $name) {
// ...
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
Route Groups
Route groups allow you to share route attributes, such as middleware, namespaces, or prefixes, across a large number of routes without defining those attributes on each individual route.
Route Prefixing
The prefix method can be used to prefix each route in the group with a given URI. This is common for admin panels.
Route::prefix('admin')->group(function () {
// URI: /admin/users
Route::get('/users', function () {
// Matches The "/admin/users" URL
});
// URI: /admin/settings
Route::get('/settings', function () {
// Matches The "/admin/settings" URL
});
});
Domain Routing
Route groups may also be used to handle subdomain routing. The subdomain may be specified using the domain method.
Route::domain('account.myapp.com')->group(function () {
Route::get('user/{id}', function ($id) {
// Only matches if the user visits account.myapp.com
});
});
Note: Parameters from the domain can also be captured (e.g.,
{account}.myapp.com).
4. URL Generation
The framework provides helpers to assist in generating URLs for your application. This is essential for building links in your templates and API responses.
The Current URL
You may access information about the current request URL using the url helper or the Request facade.
// Get the current URL without query string
$current = url()->current();
// Get the current URL including query string
$full = url()->full();
// Get the URL for the previous request
$previous = url()->previous();
Generating Framework URLs
To generate a URL for a specific path within your application:
$url = url('/posts/10');
// Output: http://example.com/posts/10
Generating Asset URLs
The asset helper is used to generate a URL to the public directory of the application. This is used for CSS, JavaScript, and Images. It automatically handles HTTP vs HTTPS based on the current request configuration.
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<img src="{{ asset('img/logo.png') }}" alt="Logo">
Output:
http://your-domain.com/css/app.css
Generation Shortcuts (Route Helpers)
As mentioned in Advanced Routing, the most common shortcut for URL generation is the route() helper function.
Advantages:
- Maintainability: If the route path changes in
web.php(e.g., from/usersto/members), theroute()helper automatically generates the new path without code changes in the view. - Parameters: It handles parameter injection automatically.
Route::get('/post/{id}', [PostController::class, 'show'])->name('post.show');
// In Controller or View:
echo route('post.show', ['id' => 1]);
// Output: http://example.com/post/1
Signed URLs:
Frameworks often support "signed" URLs, which attach a hash to the URL to verify that the URL has not been modified since it was created. This is useful for "Unsubscribe" links or "Password Reset" links.
use Illuminate\Support\Facades\URL;
return URL::signedRoute('unsubscribe', ['user' => 1]);