Full Example
This example demonstrates a complete routing setup for a simple e-commerce application.
Project Structure
Section titled “Project Structure”project/├── Controllers/│ ├── HomeController.php│ ├── AuthController.php│ ├── ProductController.php│ └── OrderController.php├── Middleware/│ ├── AuthMiddleware.php│ ├── GuestMiddleware.php│ └── CsrfMiddleware.php├── routes/│ └── web.php└── index.phpMiddleware Examples
Section titled “Middleware Examples”AuthMiddleware.php
Section titled “AuthMiddleware.php”<?php
namespace Middleware;
class AuthMiddleware{ public function handle(callable $next) { if (!isset($_SESSION['user_id'])) { $_SESSION['redirect_after_login'] = $_SERVER['REQUEST_URI']; header('Location: /login'); exit; }
$next(); }}GuestMiddleware.php
Section titled “GuestMiddleware.php”<?php
namespace Middleware;
class GuestMiddleware{ public function handle(callable $next) { if (isset($_SESSION['user_id'])) { header('Location: /dashboard'); exit; }
$next(); }}CsrfMiddleware.php
Section titled “CsrfMiddleware.php”<?php
namespace Middleware;
class CsrfMiddleware{ public function handle(callable $next) { $token = $_POST['csrf_token'] ?? ''; $sessionToken = $_SESSION['csrf_token'] ?? '';
if (!hash_equals($sessionToken, $token)) { http_response_code(403); echo 'CSRF token mismatch'; exit; }
$next(); }}Controller Examples
Section titled “Controller Examples”HomeController.php
Section titled “HomeController.php”<?php
namespace Controllers;
class HomeController{ public function index() { $products = $this->getFeaturedProducts(); require __DIR__ . '/../views/home.php'; }
public function about() { require __DIR__ . '/../views/about.php'; }
private function getFeaturedProducts() { // Database query here return []; }}ProductController.php
Section titled “ProductController.php”<?php
namespace Controllers;
class ProductController{ public function index() { $products = $this->getAllProducts(); require __DIR__ . '/../views/products/index.php'; }
public function show(string $id) { $product = $this->findProduct($id);
if (!$product) { http_response_code(404); require __DIR__ . '/../views/errors/404.php'; return; }
require __DIR__ . '/../views/products/show.php'; }
private function getAllProducts() { // Database query return []; }
private function findProduct(string $id) { // Database query return null; }}OrderController.php
Section titled “OrderController.php”<?php
namespace Controllers;
class OrderController{ public function index() { $userId = $_SESSION['user_id']; $orders = $this->getUserOrders($userId); require __DIR__ . '/../views/orders/index.php'; }
public function show(string $id) { $order = $this->findOrder($id);
// Verify ownership if (!$order || $order['user_id'] !== $_SESSION['user_id']) { http_response_code(403); echo 'Access denied'; return; }
require __DIR__ . '/../views/orders/show.php'; }
public function checkout() { $cart = $_SESSION['cart'] ?? []; require __DIR__ . '/../views/checkout.php'; }
public function processCheckout() { // Validate payment $orderId = $this->createOrder($_POST);
// Redirect to confirmation header("Location: /orders/{$orderId}/confirmation"); exit; }
public function confirmation(string $id) { $order = $this->findOrder($id); require __DIR__ . '/../views/orders/confirmation.php'; }
private function getUserOrders(int $userId) { // Database query return []; }
private function findOrder(string $id) { // Database query return null; }
private function createOrder(array $data) { // Create order in database return uniqid('order_'); }}Routes Configuration
Section titled “Routes Configuration”routes/web.php
Section titled “routes/web.php”<?php
use Krag\Sroute\Router;use Controllers\HomeController;use Controllers\AuthController;use Controllers\ProductController;use Controllers\OrderController;
$router = new Router();
// Register middleware aliases$router->aliasMiddleware('auth', \Middleware\AuthMiddleware::class);$router->aliasMiddleware('guest', \Middleware\GuestMiddleware::class);$router->aliasMiddleware('csrf', \Middleware\CsrfMiddleware::class);
// ============================================// Public Routes// ============================================
$router->get('/', HomeController::class, 'index') ->name('home');
$router->get('/about', HomeController::class, 'about') ->name('about');
// Products$router->get('/products', ProductController::class, 'index') ->name('products.index');
$router->get('/products/{id}', ProductController::class, 'show') ->name('products.show');
// ============================================// Guest Routes (Unauthenticated Only)// ============================================
$router->get('/login', AuthController::class, 'showLogin') ->middleware(['guest']) ->name('auth.login.get');
$router->post('/login', AuthController::class, 'login') ->middleware(['csrf', 'guest']) ->name('auth.login.post');
$router->get('/register', AuthController::class, 'showRegister') ->middleware(['guest']) ->name('auth.register.get');
$router->post('/register', AuthController::class, 'register') ->middleware(['csrf', 'guest']) ->name('auth.register.post');
// ============================================// Authenticated Routes// ============================================
$router->get('/logout', AuthController::class, 'logout') ->middleware(['auth']) ->name('auth.logout');
// Orders$router->get('/orders', OrderController::class, 'index') ->middleware(['auth']) ->name('orders.index');
$router->get('/orders/{id}', OrderController::class, 'show') ->middleware(['auth']) ->name('orders.show');
$router->get('/checkout', OrderController::class, 'checkout') ->middleware(['auth']) ->name('checkout.get');
$router->post('/checkout', OrderController::class, 'processCheckout') ->middleware(['csrf', 'auth']) ->name('checkout.post');
$router->get('/orders/{id}/confirmation', OrderController::class, 'confirmation') ->middleware(['auth']) ->name('orders.confirmation');
// Dispatch the router$router->load();Middleware Execution Order
Section titled “Middleware Execution Order”Remember that middleware executes in LIFO (Last-In-First-Out) order:
$router->post('/checkout', OrderController::class, 'processCheckout') ->middleware(['csrf', 'auth']);Execution flow:
AuthMiddlewareruns first (last in array)CsrfMiddlewareruns second (first in array)OrderController::processCheckout()runs last
This ensures the user is authenticated before CSRF validation occurs.
Key Takeaways
Section titled “Key Takeaways”- Organize by feature: Group related routes together
- Use middleware wisely: Apply authentication and CSRF protection where needed
- Name your routes: Makes URL generation easier and more maintainable
- Keep controllers thin: Delegate business logic to service classes
- Understand LIFO: Middleware order matters for proper request filtering