Unit 3 - Notes

INT221 7 min read

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:

BASH
php artisan make:controller UserController

Basic Class Structure:

PHP
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:

PHP
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:

  1. In the Route definition:

    PHP
        Route::get('profile', [UserController::class, 'show'])->middleware('auth');
        

  2. In the Controller Constructor:
    This allows for more granular control, such as applying middleware to specific methods.

    PHP
        class 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:

BASH
php artisan make:controller PhotoController --resource

Registering the Route:

PHP
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.

HTML
Hello, {{ $name }}.

2. Displaying Unescaped Data:
If you need to output HTML explicitly (use with caution):

HTML
Hello, {!! $name !!}.

3. Rendering JSON:
Blade provides a directive to render variables as JSON for JavaScript usage.

HTML
<script>
    var appData = @json($array);
</script>

Control Structures

Blade provides convenient shortcuts for common PHP control structures.

Conditionals:

BLADE
@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:

BLADE
@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
<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.

BLADE
@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:

PHP
Route::get('/user/profile', [UserProfileController::class, 'show'])->name('profile');

Usage:

PHP
// 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:

PHP
// 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.

PHP
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.

PHP
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.

PHP
// 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:

PHP
$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.

BLADE
<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:

  1. Maintainability: If the route path changes in web.php (e.g., from /users to /members), the route() helper automatically generates the new path without code changes in the view.
  2. Parameters: It handles parameter injection automatically.

PHP
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.

PHP
use Illuminate\Support\Facades\URL;

return URL::signedRoute('unsubscribe', ['user' => 1]);