PHP code example of hengeb / router

1. Go to this page and download the library: Download hengeb/router library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

hengeb / router example snippets


use App\Service\Router\Router;
use Symfony\Component\HttpFoundation\Request;

(will also look in subdirectories)
$router = new Router(__DIR__ . '/../Classes/Controller');
$request = Request::createFromGlobals();
$router->dispatch($request)->send();

use Hengeb\Router\Attribute\Route;
use Hengeb\Router\Attribute\AllowIf;
use Hengeb\Router\Attribute\Inject;
use Hengeb\Router\Attribute\PublicAccess;
use Hengeb\Router\Attribute\RequestValue;
use Hengeb\Router\Attribute\RequireLogin;
use Hengeb\Router\Interface\CurrentUserInterface;
use Hengeb\Db\Db;
use Symfony\Component\HttpFoundation\Response;

class MyController extends Controller {
    // the router will inject the TemplateEngine service directly after it created the object
    #[Inject]
    public TemplateEngine $templates;

    // the router will inject the Logger service when it creates the object
    public function __construct(
        private Logger $logger,
    ) {}

    // the route matcher starts with the HTTP method, followed by the path. You can use some regular expressions to some extend
    // do not use the ? symbol because this separates the query from the path)
    // this will match /search and / and also /search/ and also /search?foo=bar but not /search?q=theQuery because of the next route
    // note: one of the Access attributes is mandatory
    #[Route('GET /(search|)'), PublicAccess]
    public function form(): Response {
        return $this->render('SearchController/search');
    }

    // you can use identifiers in the path or in the query, they will be passed as arguments and casted to the desired type
    // the Db object will be injected (in this case via the Db::getInstance() method)
    #[Route('GET /(search|)?q={query}', PublicAccess]
    public function search(string $query, Db $db): Response {
        $sql = $this->buildQuery($query);
        $results = $db->query($sql);
        return $this->showResults($ids);
    }

    // access control: only allow logged-in users
    // the dispatch method needs a second argument that implements the CurrentUserInterface
    #[Route('GET /users'), RequireLogin]
    public function users(): Response {
        ...
    }


    #[Route('GET /group/{group}'), RequireLogin]
    // the group object will be fetched from the database and injected
    public function show(Group $group): Response {
        ...
    }

    // you can have multiple route matchers, make sure they fit together
    // \d+ regex for number, get the user object by its id
    #[Route('GET /user/{\d+:id=>user}'), RequireLogin]
    // if the above matcher does not fit, get the user by its username
    #[Route('GET /user/{username=>user}'), RequireLogin]
    // the user object will be fetched from the database and injected
    public function show(User $user): Response {
        ...
    }

    // access control: only give access if the current user has the admin role OR is the user himself/herself
    // this will look for a method like hasRole, getRole, isRole, role, get("role") and so on
    // the '$user->get("id")' is a template string that will be evaluated. This does only allow simple function calls because the string will be parsed.
    #[Route('GET /user/{username=>user}/edit'), AllowIf(role: 'admin'), AllowIf(id: '$user->get("id")')]
    public function edit(User $user): Response {
        ...
    }

    // this route will only match if the method is POST
    // this will also check for a POST variable _csrfToken and validate it to prevent CSRF attacks
    // you can override this setting the CheckCsrfToken(false) attribute
    // generate the CSRF token with $router->createCsrfToken()
    // $username and $password will be injected from the request body
    #[Route('POST /login'), PublicAccess]
    public function login(#[RequestValue] string $username, #[RequestValue] string $password) {

    }

    // you can inject the router object, the request, the current user
    #[Route('GET /foo'), PublicAccess]
    public function foo(Request $request, CurrentUserInterface $user, Router $router) {
        ...
    }
}

$router->addType(User::class, fn($id) => User::find($id), 'id')

class User implements RetrievableModel {
    public function retrieveModel($userId): ?static {
        return UserRepository::getInstance()->findOneById((int)$userId);
    }
}

$templateEngine = new TemplateEngine();
$router->addService(TemplateEngine::class, $templateEngine);

$router->addExceptionHandler(InvalidRouteException::class, [Controller::class, 'handleException']);

$router->addExceptionHandler(InvalidRouteException::class, fn(\Exception $e) => die($e->getMessage()));