Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Ahondev/portfolio-v2/llms.txt

Use this file to discover all available pages before exploring further.

The Web Router is the layer that maps incoming HTTP requests to your React/Vite SPA views without ever touching WordPress’s own template hierarchy. WebRoute is a static facade you use inside configuration/routes/web.php; WebRouter is the singleton that stores routes, auto-creates WP pages in development, and dispatches the actual request at wp_loaded priority 5.

WebRoute Facade

WebRoute delegates every call to the WebRouter singleton, giving you a clean static API that reads like a standard web framework router.

WebRoute::get()

Register a GET route pointing to a controller action.
public static function get(
    string $path,
    string $name,
    array  $controller
): WebRouteDefinition
path
string
required
The URI path to match, e.g. '/' or '/contact'. Leading slash required.
name
string
required
Human-readable name used as the WordPress page title when the route is auto-registered in development mode.
controller
array
required
A two-element array: [ControllerClass::class, 'methodName']. The controller must extend WebController.
use Ahon\WPCMS\Routing\Web\WebRoute as Route;

Route::get('/', 'Accueil', [HomeController::class, 'home']);
Route::get('/contact', 'Contact', [HomeController::class, 'contact']);

WebRoute::post()

Register a POST route.
public static function post(
    string $path,
    string $controller,
    string $name,
    bool   $auth = false
): WebRouteDefinition
path
string
required
The URI path to match.
controller
string
required
The controller class name string. Note: the source type hint is string but the internal implementation accesses it with array index notation — pass a two-element array [ControllerClass::class, 'methodName'] exactly as you would for get().
name
string
required
Human-readable route name.
auth
bool
When true, restricts the route to logged-in users. Defaults to false.

WebRoute::CPT()

Bind a custom post type to both an archive URL and individual single-post URLs under a shared base path.
public static function CPT(
    string $path,
    string $postType,
    string $controller
): void
path
string
required
The base URL prefix, e.g. '/blog'. The router will match /blog (archive) and /blog/{slug} (single) automatically.
postType
string
required
The EloquentCPT subclass. The router reads $postType::$model to look up WordPress posts.
controller
string
required
A controller class that implements both archive() and single(?EloquentCPT $post) methods.
use Ahon\WPCMS\App\PostTypes\Article;

Route::CPT('/blog', Article::class, BlogController::class);
Your CPT controller must implement both archive(): string and single(?EloquentCPT $post): string methods. The router calls these directly by name — no interface is enforced at compile time, but a missing method causes the request to return false silently.

WebRoute::group()

Prepend a shared prefix to an array of existing route paths. Pass the route paths (strings) returned by earlier get() / post() calls.
public static function group(
    string $prefix,
    array  $route_ids
): void
prefix
string
required
The path segment to prepend to every listed route.
route_ids
array
required
An array of route path strings that were already registered.

WebRouter (Singleton)

WebRouter is the engine behind the facade. It is instantiated once by WebRouter::init() and stored as a static property.

WebRouter::init()

Creates a new WebRouter instance, loads configuration/routes/web.php to populate the route table, and returns the singleton.
public static function init(): WebRouter
Called automatically by the Kernel at wp_loaded priority 5. You should not call this manually.

WebRouter::instance()

Returns the existing singleton after init() has been called.
public static function instance(): WebRouter
Useful inside service providers or controllers to inspect registered routes.

addRoute()

Registers a WebRouteDefinition into the route table keyed by its path. In development mode it also calls registerPage() to create the corresponding WordPress page.
public function addRoute(WebRouteDefinition $route): WebRouteDefinition

registerCPT()

Registers a CPT route configuration. In development mode a WordPress archive page is created automatically.
public function registerCPT(
    string $path,
    string $postType,
    string $controller
): void

handleRequest()

The main request dispatcher. Reads $_SERVER['REQUEST_URI'], skips internal WordPress paths (/wp/, /api/, /uploads/, /admin, /client), optionally serves an HTML static-cache file to bots, and then dispatches to the matching controller action.
public function handleRequest(): bool
Returns false when no route matches or when the request targets a WordPress-reserved path. Returns true (and exits) when a route is matched and output has been sent. Dispatch logic:
1

Check ignored paths

If the URI starts with /wp/, /api/, /uploads/, /admin, or /client, return false immediately.
2

Bot detection & static cache

If the visitor is identified as a bot and a pre-rendered HTML file exists in the SSG cache, serve it directly and exit.
3

Static route match

Look up the full URI in $routes. If found, instantiate the controller and call its method, echo the output, and exit.
4

CPT route match

Iterate $cptRoutes. If the URI equals the base path, call archive(). If it starts with the base path followed by a slug, look up the post and call single($eloquentPost).

getCurrentURI()

Returns the current request path, stripping the trailing slash (root / is left as-is).
public function getCurrentURI(): string

pathToSlug() / slugToPath()

Utility methods that convert between URI paths and WordPress page slugs. The root path / maps to the slug 'home'.
public function pathToSlug(string $path): string
public function slugToPath(string $slug): string

routes() / cptRoutes()

Return the internal route tables.
public function routes(): array     // keyed by path
public function cptRoutes(): array  // keyed by base path

getCacheablePages()

Returns all published WordPress posts that can be statically generated: the built-in page post type plus every post type registered via CPT().
public function getCacheablePages(): array
Used by SSGServiceProvider to build the static-site generator’s page list.

WebRouteDefinition Properties

WebRouteDefinition is the value object returned by WebRoute::get() and WebRoute::post().
PropertyTypeDescription
$httpMethodHttpMethodThe HTTP verb enum (GET, POST, …)
$namestringHuman-readable page name
$pathstringThe URI path (mutable — group() prepends to it)
$controllerstringFully-qualified controller class name
$methodstringController method to invoke

Complete Routes File Example

<?php
// configuration/routes/web.php

use Ahon\WPCMS\App\Controllers\Web\HomeController;
use Ahon\WPCMS\App\Controllers\Web\BlogController;
use Ahon\WPCMS\App\Controllers\Web\ServiceController;
use Ahon\WPCMS\App\PostTypes\Article;
use Ahon\WPCMS\App\PostTypes\Service;
use Ahon\WPCMS\Routing\Web\WebRoute as Route;

// Static pages
Route::get('/', 'Accueil', [HomeController::class, 'home']);
Route::get('/agence', 'Agence', [HomeController::class, 'agence']);
Route::get('/devis', 'Devis', [HomeController::class, 'devis']);
Route::get('/contact', 'Contact', [HomeController::class, 'contact']);

// Custom post type routes — handles /services, /services/{slug}
Route::CPT('/services', Service::class, ServiceController::class);

// Blog — handles /blog, /blog/{slug}
Route::CPT('/blog', Article::class, BlogController::class);

WebController Base Class

Controllers handling web routes must extend WebController. The key methods are view() and postView():
// Render a view for a standard page (no post)
public function view(string $view, array $data = [], ?EloquentCPT $post = null): string

// Shorthand: render a view with an EloquentCPT post bound as $data['post']
public function postView(string $view, ?EloquentCPT $post, $data = []): string
The view() method:
  1. Collects Vite asset URLs via Vite::instance()->assets()
  2. Merges view composer data from ComposerManager
  3. Resolves SEO meta from ACF fields (page meta for static routes, post properties for CPT routes)
  4. In ?json=1 mode, returns a JSON payload for SPA client-side navigation
  5. Otherwise renders src/SSR/client.php which outputs the full HTML shell
class HomeController extends WebController
{
    public function home(): string
    {
        return $this->view('Home', [
            'hero' => get_field('hero', 'option'),
        ]);
    }
}

class BlogController extends WebController
{
    public function archive(): string
    {
        $posts = Article::query()->orderBy('date', DESC)->all();
        return $this->view('Blog', ['posts' => $posts]);
    }

    public function single(?Article $post): string
    {
        return $this->postView('Article', $post);
    }
}

Build docs developers (and LLMs) love