### Installation Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Install Waypoint using Composer. ```bash composer require ascetic-soft/waypoint ``` -------------------------------- ### Quick Start Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Register routes and handle requests using Waypoint. ```php use AsceticSoft\Waypoint\RouteRegistrar; use AsceticSoft\Waypoint\Router; use Nyholm\Psr7\ServerRequest; // 1. Register routes $registrar = new RouteRegistrar(); $registrar->get('/hello/{name}', function (string $name) use ($responseFactory) { $response = $responseFactory->createResponse(); $response->getBody()->write("Hello, {$name}!"); return $response; }); // 2. Create the router and handle requests $router = new Router($container, $registrar->getRouteCollection()); $request = new ServerRequest('GET', '/hello/world'); $response = $router->handle($request); ``` -------------------------------- ### Install Dependencies Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command to install project dependencies using Composer. ```bash composer install ``` -------------------------------- ### Exception Handling Example Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Illustrates how to catch specific Waypoint exceptions during request handling. ```php use AsceticSoft\Waypoint\Exception\RouteNotFoundException; use AsceticSoft\Waypoint\Exception\MethodNotAllowedException; try { $response = $router->handle($request); } catch (RouteNotFoundException $e) { // Return 404 response } catch (MethodNotAllowedException $e) { // Return 405 response with Allow header $allowed = implode(', ', $e->getAllowedMethods()); } ``` -------------------------------- ### Dependency Injection in Route Handlers Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Example demonstrating how RouteHandler automatically resolves controller method parameters, including route parameters, container services, and default/nullable values. ```php #[Route('/orders/{id:\d+}', methods: ['GET'])] public function show( int $id, // route parameter (auto-cast) ServerRequestInterface $request, // current request OrderRepository $repo, // resolved from container ?LoggerInterface $logger = null, // container or default ): ResponseInterface { // ... } ``` -------------------------------- ### Route Groups Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Example of grouping related routes under a shared prefix and middleware, including nested groups. ```php $registrar->group('/api', function (RouteRegistrar $registrar) { $registrar->group('/v1', function (RouteRegistrar $registrar) { $registrar->get('/users', [UserController::class, 'list']); // Matches: /api/v1/users }); $registrar->group('/v2', function (RouteRegistrar $registrar) { $registrar->get('/users', [UserV2Controller::class, 'list']); // Matches: /api/v2/users }); }, middleware: [ApiAuthMiddleware::class]); ``` -------------------------------- ### CI Static Analysis Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command for static analysis as run in CI. ```bash vendor/bin/phpstan analyse ``` -------------------------------- ### Absolute URL Generation Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Demonstrates how to set a base URL and generate absolute URLs using the router. ```php $router->setBaseUrl('https://example.com'); $url = $router->getUrlGenerator()->generate('users.show', ['id' => 42], absolute: true); // => https://example.com/users/42 ``` -------------------------------- ### Route Caching - Deployment/Cache Warm-up Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Compiling routes to a PHP file for zero-overhead loading in production during deployment or cache warm-up. ```php use AsceticSoft\Waypoint\Cache\RouteCompiler; // During deployment / cache warm-up $registrar = new RouteRegistrar(); $registrar->scanDirectory(__DIR__ . '/Controllers', 'App\\Controllers'); $compiler = new RouteCompiler(); $compiler->compile($registrar->getRouteCollection(), __DIR__ . '/cache/routes.php'); ``` -------------------------------- ### Direct UrlGenerator Usage Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Shows how to use the UrlGenerator directly for generating relative and absolute URLs. ```php use AsceticSoft\Waypoint\UrlGenerator; $generator = new UrlGenerator($router->getRouteCollection(), 'https://example.com'); $url = $generator->generate('users.show', ['id' => 42]); // relative $url = $generator->generate('users.show', ['id' => 42], absolute: true); // absolute ``` -------------------------------- ### Static Analysis Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command to perform static analysis using PHPStan with the project's configuration. ```bash vendor/bin/phpstan analyse --configuration=phpstan.neon.dist ``` -------------------------------- ### Development Tasks with Makefile Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Common development tasks available via the project's Makefile. ```bash make fix # Auto-fix code style (PHP CS Fixer) make cs-check # Check code style (dry-run) make stan # Run PHPStan static analysis (level 9) make test # Run PHPUnit tests make check # Run all checks (cs-check + stan + test) make all # Fix code style, then run stan and tests ``` -------------------------------- ### Route Parameters Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Defining routes with FastRoute-style placeholders for parameters, including basic, constrained, and multiple parameters. ```php // Basic parameter — matches any non-slash segment $registrar->get('/users/{id}', [UserController::class, 'show']); // Constrained parameter — only digits $registrar->get('/users/{id:\d+}', [UserController::class, 'show']); // Multiple parameters $registrar->get('/posts/{year:\d{4}}/{slug}', [PostController::class, 'show']); ``` ```php $registrar->get('/users/{id:\d+}', function (int $id) { // $id is automatically cast to int }); ``` -------------------------------- ### Composer Metadata Sanity Check Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command to validate the composer.json file. ```bash composer validate --strict ``` -------------------------------- ### Full Local Verification Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command to run all local checks including code style, static analysis, and tests. ```bash make check ``` -------------------------------- ### Focused Tests Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command to run specific tests using PHPUnit. ```bash vendor/bin/phpunit tests/RouterTest.php ``` ```bash vendor/bin/phpunit --filter testName ``` -------------------------------- ### Route Caching - Runtime Loading Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Loading routes from a cache file at runtime if the cache is fresh, otherwise recompiling and loading. ```php // At runtime — load from cache $cacheFile = __DIR__ . '/cache/routes.php'; $compiler = new RouteCompiler(); $router = new Router($container); if ($compiler->isFresh($cacheFile)) { $router->loadCache($cacheFile); } else { $registrar = new RouteRegistrar(); $registrar->scanDirectory(__DIR__ . '/Controllers', 'App\\Controllers'); $compiler->compile($registrar->getRouteCollection(), $cacheFile); $router = new Router($container, $registrar->getRouteCollection()); } ``` -------------------------------- ### Route-level Middleware Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Applying middleware to specific routes during registration. ```php $registrar->get('/admin/dashboard', [AdminController::class, 'dashboard'], middleware: [AdminAuthMiddleware::class], ); ``` -------------------------------- ### Global Middleware Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Adding global middleware to the Router that runs for every matched route. ```php $router->addMiddleware(CorsMiddleware::class); $router->addMiddleware(new RateLimitMiddleware(limit: 100)); ``` -------------------------------- ### CI Test Coverage Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command to run tests and generate coverage report for CI. ```bash vendor/bin/phpunit --coverage-clover coverage.xml ``` -------------------------------- ### Loading Attributes Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Loading routes defined by attributes, either by specifying controller classes or scanning directories. ```php $registrar = new RouteRegistrar(); // Load specific controller classes $registrar->loadAttributes( UserController::class, PostController::class, ); // Or scan an entire directory $registrar->scanDirectory(__DIR__ . '/Controllers', 'App\Controllers'); // Optionally filter by filename pattern (e.g. only *Controller.php files) $registrar->scanDirectory(__DIR__ . '/Controllers', 'App\Controllers', '*Controller.php'); ``` -------------------------------- ### CI Code Style Check Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command to check code style in CI environment without fixing. ```bash vendor/bin/php-cs-fixer fix --dry-run --diff ``` -------------------------------- ### Route Diagnostics - Listing and Conflict Detection Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Using RouteDiagnostics to inspect registered routes, list them, and detect potential issues like duplicate paths, names, or shadowed routes. ```php use AsceticSoft\Waypoint\Diagnostic\RouteDiagnostics; $diagnostics = new RouteDiagnostics($router->getRouteCollection()); // Print a formatted route table $diagnostics->listRoutes(); // Detect conflicts $report = $diagnostics->findConflicts(); if ($report->hasIssues()) { $diagnostics->printReport(); } ``` -------------------------------- ### Manual Route Registration Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Registering routes using the RouteRegistrar fluent API with shortcut methods for common HTTP verbs. ```php use AsceticSoft\Waypoint\RouteRegistrar; $registrar = new RouteRegistrar(); // Full form $registrar->addRoute('/users', [UserController::class, 'list'], methods: ['GET']); // Shortcuts $registrar->get('/users', [UserController::class, 'list']); $registrar->post('/users', [UserController::class, 'create']); $registrar->put('/users/{id}', [UserController::class, 'update']); $registrar->delete('/users/{id}', [UserController::class, 'destroy']); // Any other HTTP method (PATCH, OPTIONS, etc.) $registrar->addRoute('/users/{id}', [UserController::class, 'patch'], methods: ['PATCH']); ``` ```php $router = new Router($container, $registrar->getRouteCollection()); ``` -------------------------------- ### Auto-fix Style Source: https://github.com/ascetic-soft/waypoint/blob/main/AGENTS.md Command to automatically fix code style issues in src/ and tests/ directories. ```bash make fix ``` -------------------------------- ### URL Generation Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Generating URLs from named routes using reverse routing, including parameters and query strings. ```php // Register named routes $registrar->get('/users', [UserController::class, 'list'], name: 'users.list'); $registrar->get('/users/{id:\d+}', [UserController::class, 'show'], name: 'users.show'); $router = new Router($container, $registrar->getRouteCollection()); // Generate URLs $url = $router->getUrlGenerator()->generate('users.show', ['id' => 42]); // => /users/42 $url = $router->getUrlGenerator()->generate('users.list', query: ['page' => 2, 'limit' => 10]); // => /users?page=2&limit=10 ``` -------------------------------- ### Attribute-Based Routing Source: https://github.com/ascetic-soft/waypoint/blob/main/README.md Declaring routes directly on controller classes using the #[Route] attribute, including class-level prefixes and method-level route definitions. ```php use AsceticSoft\Waypoint\Attribute\Route; #[Route('/api/users', middleware: [AuthMiddleware::class])] class UserController { #[Route('/', methods: ['GET'], name: 'users.list')] public function list(): ResponseInterface { /* ... */ } #[Route('/{id:\d+}', methods: ['GET'], name: 'users.show')] public function show(int $id): ResponseInterface { /* ... */ } #[Route('/', methods: ['POST'], name: 'users.create')] public function create(ServerRequestInterface $request): ResponseInterface { /* ... */ } #[Route('/{id:\d+}', methods: ['PUT'], name: 'users.update')] public function update(int $id, ServerRequestInterface $request): ResponseInterface { /* ... */ } #[Route('/{id:\d+}', methods: ['DELETE'], name: 'users.delete')] public function delete(int $id): ResponseInterface { /* ... */ } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.