yeremi / route-mapper
A PHP library for mapping and resolving routes using attributes.
Installs: 31
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 2
Forks: 0
Open Issues: 0
pkg:composer/yeremi/route-mapper
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.65.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^9.5
This package is auto-updated.
Last update: 2026-01-27 09:05:01 UTC
README
RouteMapper is a lightweight, framework-agnostic PHP library that uses PHP 8 attributes to map and resolve API route paths defined via PHP attributes in a simple and explicit way.
It focuses on one responsibility only: mapping routes to methods, without imposing an HTTP framework or execution model.
Design Philosophy
- RouteMapper focuses on one responsibility only: mapping routes to methods.
- It does not handle HTTP requests, middleware, controllers, or responses.
- Integration is explicit by design — no magic containers or hidden behavior.
- The library favors clarity over convenience.
- If you need a full routing framework, RouteMapper is probably not the right tool.
Key Features
- Attribute-Based Routing using PHP 8 attributes
- Framework-Agnostic (works with any HTTP client or framework)
- Lightweight & Focused — no unnecessary abstractions
- Explicit Route Resolution — no magic, full control
- Modern PHP — strict typing and PHP 8 features
Requirements
- PHP 8.0 or higher
Why Use RouteMapper?
Use RouteMapper when you want to keep routing metadata close to your code (via attributes) and still remain framework-agnostic. It works well for SDKs, API clients, small services, and projects that want explicit, testable route resolution without adopting a full stack.
Installation
Install RouteMapper via Composer:
composer require yeremi/route-mapper
Example Usage
Routes are resolved using the class name and method name.
Defining routes with attributes
use Yeremi\RouteMapper\Attribute\ApiRoute; use Yeremi\RouteMapper\Registry\RouteRegistry; use Yeremi\RouteMapper\Resolver\RouteResolver; // (for this example): `composer require guzzlehttp/guzzle` use GuzzleHttp\Client; // Example only class UserRepository { public function __construct( protected RouteRegistry $routeRegistry, protected RouteResolver $routeResolver, protected Client $httpClient ) { // Registers all #[ApiRoute] attributes in this class $this->routeRegistry->registerRoutes($this); } #[ApiRoute('/users')] // Defines only the route path public function fetchAll(): void { $route = $this->resolveRoute(__FUNCTION__); $response = $this->httpClient->get($route); echo $response->getBody()->getContents(); } #[ApiRoute('/user/{id}')] public function fetchOne(int $id): void { $route = $this->resolveRoute(__FUNCTION__, ['id' => $id]); $response = $this->httpClient->get($route); if ($response->getStatusCode() === 200) { $data = json_decode($response->getBody()->getContents(), true); // Process the $data as needed. } } #[ApiRoute('/user/create')] public function create(array $data): void { $route = $this->resolveRoute(__FUNCTION__); $response = $this->httpClient->post($route, [ 'json' => $data, ]); echo "User Created: " . $response->getBody()->getContents() . "\n"; } #[ApiRoute('/user/{id}/update')] public function update(int $id, array $data): void { $parameters = ['id' => $id]; $route = $this->resolveRoute(__FUNCTION__, $parameters); $response = $this->httpClient->put($route, [ 'json' => $data, ]); echo "User Updated: " . $response->getBody()->getContents() . "\n"; } #[ApiRoute('/user/{id}/delete')] public function delete(int $id): void { $parameters = ['id' => $id]; $route = $this->resolveRoute(__FUNCTION__, $parameters); $response = $this->httpClient->delete($route); echo "User Deleted: " . $response->getBody()->getContents() . "\n"; } private function resolveRoute(string $methodName, array $parameters = []): string { $route = $this->routeRegistry->getRoute(static::class, $methodName); if (!$route) { throw new \RuntimeException("Route not found for method: $methodName"); } return $this->routeResolver->resolve($route, $parameters); } } // Usage example: $routeRegistry = new RouteRegistry(); $routeResolver = new RouteResolver(); $httpClient = new Client([ 'base_uri' => 'https://api.example.com', 'timeout' => 5.0, ]); $userRepository = new UserRepository($routeRegistry, $routeResolver, $httpClient); // Fetch one user $userRepository->fetchOne(123); // Fetch all users $userRepository->fetchAll(); // Create a user $userRepository->create(['name' => 'John Doe', 'email' => 'john@example.com']); // Update a user $userRepository->update(123, ['name' => 'John Doe Updated']); // Delete a user $userRepository->delete(123);
Note: RouteMapper does not perform HTTP requests. Any HTTP client (Guzzle, Symfony HttpClient, etc.) can be used.
Comparison with Other Solutions
| Feature | RouteMapper | Symfony Routing | Laravel Routing | Slim Framework |
|---|---|---|---|---|
| Attribute-based | ✅ | ✅ | ❌ | ❌ |
| Framework-Agnostic | ✅ | ❌ | ❌ | ✅ |
| Lightweight | ✅ | ⚠️ | ❌ | ✅ |
| Explicit resolution | ✅ | ❌ | ❌ | ⚠️ |
Acknowledgments
Inspired by the flexibility of modern PHP attributes and the simplicity of middleware-based frameworks.
License
RouteMapper is licensed under the MIT License. See the LICENSE file for details.