Routes & Navigation

Routing System
Your Navigation Hub

Zenith's routing system acts as your mission control — intelligently mapping requests to destinations with attribute-based configuration and middleware for secure, efficient navigation.

Key Features

Built for Precision Navigation

Every route comes equipped with the essential systems you need for safe, efficient request handling across any scale of application.

PHP 8 Attributes

Define routes directly on controller methods with modern annotations.

Modern Declarative
Middleware Security

Built-in authentication, authorization, and custom security layers.

Role-based Extensible
RESTful Design

Explicit HTTP method mapping with proper REST conventions.

RESTful Standards
High Performance

Optimized route matching and efficient request dispatching.

Fast Optimized

Core Operations Made Simple

Like a well-designed starship console, each routing operation is intuitive, powerful, and designed to get you where you need to go without friction.

Attribute-Based Routing

Define routes with PHP 8 attributes for clean, organized code
#[HttpMethod('GET')]
#[Auth(['admin'])]
public function dashboard(): void {
    $this->render('admin/dashboard');
}

// Multiple HTTP methods
#[HttpMethod(['GET', 'POST'])]
public function contact(): void {
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $this->handleContactForm();
    } else {
        $this->showContactForm();
    }
}

// Public route (no Auth attribute)
#[HttpMethod('GET')]
public function index(): void {
    $this->render('home');
}

Security & Authorization

Built-in middleware for secure, role-based access control
// Requires authentication (any logged-in user)
#[Auth]
#[HttpMethod('GET')]
public function profile(): void {
    $this->render('user/profile');
}

// Requires admin role
#[Auth(['admin'])]
#[HttpMethod('GET')]
public function adminDashboard(): void {
    $this->render('admin/dashboard');
}

// Multiple roles allowed
#[Auth(['admin', 'manager'])]
#[HttpMethod(['GET', 'POST'])]
public function reports(): void {
    $this->render('reports/index');
}

// Guest only (redirects if logged in)
#[HttpMethod('GET')]
public function login(): void {
    // Middleware handled in routes registration
    $this->render('auth/login');
}

Controller Registration

Automatic route discovery based on controller methods and attributes
// Register controllers with attribute-based routing
Router::registerController('Admin', '/admin');
Router::registerController('User', '/admin/users');
Router::registerController('Client', '/admin/clients');
Router::registerController('Nexus', '/nexus');

// Manual route registration still available
Router::get('/', 'Home@index');
Router::post('/contact', 'Home@submitContact');
Router::auth('/dashboard', 'Admin@dashboard');

// Protected routes with middleware
Router::authPost('/admin/users/create', 'User@store', ['admin']);

// Set 404 handler
Router::setNotFoundHandler('Error@notFound');

// Dispatch the request
Router::dispatch();

From Blueprint to Launch

Setting up routing in Zenith is as simple as defining controller methods with attributes. Three steps to navigation mastery.

1
Add Attributes

Decorate your controller methods with HttpMethod and Auth attributes to define routing behavior.

Controller Method
#[HttpMethod('GET')]
#[Auth(['admin'])]
public function dashboard(): void
2
Register Controller

Register your controller with a base route — the system will auto-discover all method routes.

Registration
Router::registerController(
    'Admin', '/admin'
);
3
Navigate & Deploy

Your routes are live! The system handles security, method validation, and request dispatching automatically.

Result
// GET /admin/dashboard
// → AdminController::dashboard()
// ✓ Auth required: admin role

Complete Controller Example

A real-world implementation showing all the routing essentials
<?php

namespace Zenith\Controllers;

use Zenith\Attributes\Auth;
use Zenith\Attributes\HttpMethod;
use Zenith\Core\Controller;

class AdminController extends Controller {
    
    // Public route - GET /admin (index method matches base route)
    #[HttpMethod('GET')]
    public function index(): void {
        $this->render('admin/index');
    }
    
    // Protected route - GET /admin/dashboard
    #[Auth(['admin'])]
    #[HttpMethod('GET')]
    public function dashboard(): void {
        $this->render('admin/dashboard', [
            'title' => 'Admin Dashboard'
        ]);
    }
    
    // Multiple methods - GET|POST /admin/users
    #[Auth(['admin', 'manager'])]
    #[HttpMethod(['GET', 'POST'])]
    public function users(): void {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $this->handleUserCreation();
        } else {
            $this->showUserList();
        }
    }
    
    // API endpoint - POST /admin/api-data
    #[Auth(['admin'])]
    #[HttpMethod('POST')]
    public function apiData(): void {
        header('Content-Type: application/json');
        echo json_encode([
            'status' => 'success',
            'data' => $this->getApiData()
        ]);
    }
    
    private function handleUserCreation(): void {
        // Handle user creation logic
        $this->render('admin/users', [
            'message' => 'User created successfully'
        ]);
    }
    
    private function showUserList(): void {
        // Show user list logic
        $this->render('admin/users', [
            'users' => $this->getAllUsers()
        ]);
    }
}

// Routes are automatically registered like this:
// Router::registerController('Admin', '/admin');
// 
// Results in these routes:
// GET    /admin           → AdminController::index()        (public)
// GET    /admin/dashboard → AdminController::dashboard()    (admin only)
// GET    /admin/users     → AdminController::users()       (admin|manager)
// POST   /admin/users     → AdminController::users()       (admin|manager)  
// POST   /admin/api-data  → AdminController::apiData()     (admin only)
Complete Routing Reference

Your Navigation Console

Every method in your routing toolkit, organized by mission type.

Route Registration
Static
get($path, $handler, $middleware) Register a GET route with optional middleware.
Static
post($path, $handler, $middleware) Register a POST route with optional middleware.
Static
register($method, $path, $handler, $middleware) Register any HTTP method route with full control.
Static
auth($path, $handler, $middleware) Register authenticated GET route (auth middleware applied).
Static
authPost($path, $handler, $middleware) Register authenticated POST route (auth middleware applied).
Static
registerController($name, $baseRoute) Auto-register controller methods based on attributes.
Configuration & Control
Static
setNotFoundHandler($handler) Set 404 error handler for unmatched routes.
Static
setControllerNamespace($namespace) Configure the default controller namespace.
Static
setControllerSuffix($suffix) Set controller class suffix (default: 'Controller').
Static
dispatch() Process current request and route to appropriate handler.
Static
getAllRoutes() Get all registered routes (debugging purposes).
Quick Tip

Use attribute-based routing with registerController() for the most maintainable code.

Attributes & Security
Attribute
#[HttpMethod($methods)] Define which HTTP methods are allowed for this route.
Attribute
#[Auth] Require authentication (any logged-in user).
Attribute
#[Auth(['role1', 'role2'])] Require specific user roles for access.
Helper
AttributeReader::acceptsHttpMethod() Check if method accepts current HTTP method.
Route Patterns
Pattern
/admin → AdminController::index() Base route maps to index method automatically.
Pattern
/admin/users → AdminController::users() Method names become kebab-case URL segments.
Pattern
createUser → /admin/create-user camelCase methods convert to kebab-case URLs.
Pattern
Controller@method Manual route handlers use @ notation.