Quickstart

This picks up right after Getting Started — you should have http://127.0.0.1:8000/hello responding with Hello, Monad. already. Here we add a controller, a view, and organize the route with a group and a name.

Add a controller

Controller actions are plain static methods — no base class to extend, no container resolving them. Route::dispatch() calls the method directly with the matched route parameters followed by the Request:

<?php

declare(strict_types=1);

namespace App\Controllers;

use Monad\Clarity\Services\Request;
use Monad\Clarity\Services\Response;
use Monad\Clarity\Services\View;

final class GreetingController
{
    public static function show(string $name, Request $request): Response
    {
        return View::render('Greeting/show', ['name' => $name]);
    }
}

Save this as app/Controllers/GreetingController.php.

Add a view

View::render() resolves a dotted or slashed view name against app/views/ and returns a Response — the data array becomes local variables in the view, nothing implicit:

<p>Hello, <?= htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); ?>!</p>

Save this as app/views/Greeting/show.php.

Group and name the route

Route::group() shares a URI prefix (and, later, middleware) across several routes. ->name() gives a route an identifier for later reference:

use App\Controllers\GreetingController;
use Monad\Clarity\Services\Route;

Route::group(['prefix' => 'hello'], function () {
    Route::get('/{name}', [GreetingController::class, 'show'])->name('greeting.show');
});

Add this to app/routes/web.php in place of the closure-based /hello route from Getting Started — the group registers /hello/{name} for you.

Try it

curl http://127.0.0.1:8000/hello/Marshal
# <p>Hello, Marshal!</p>

Next steps

  • Routing — the full Route API: groups, named routes, typed parameters, the 404-vs-405 distinction.
  • Request/Response Lifecycle — how a request becomes a response, end to end.
  • Testing — write a test for the route you just added.