Path Handler
This library considerably simplifies API development with Mezzio by reducing amount of boilerplate code you have to write for each API operation. The idea is to provide a more convenient way to deal with:
routing - routes for all operations are registered automatically
consuming - each operation may have unique algorithm to parse request body according its content type
attributing (as in PSR-7 request attributes) - each operation may have its own set of request attributes calculated from raw request data (like current user information insteadof authentication header, validated DTO insteadof form value array, entity object insteadof query parameter with its id and so on)
producing - each operation may have unique algorithm to prepare response body from operation result according media type accepted by client
So you can focus on handling your API operations and spend less time on writing auxiliary code for request processing.
How to use?
First of all you need a project with Mezzio application. For example, you can generate one with this installer.
Next you need to declare handlers. Each handler is a set of all operations that can be performed when some path of your API is accessed with distinct HTTP methods. Any class can be a handler, you just need to annotate it with special PHP attributes:
namespace My;
use Articus\PathHandler\PhpAttribute as PHA;
use Articus\PathHandler\Exception;
use Psr\Http\Message\ServerRequestInterface;
#[PHA\Route('/entity')] //This is how you set path for handler operations
class Handler
{
#[PHA\Post()] //This is how you declare HTTP method of the operation
#[PHA\Consumer('application/json', 'Json')] //This is how you consume request body
#[PHA\Attribute('Transfer', ['type'=>'My\DTO','object_attr'=>'dto','error_attr'=>'errors'])] //This is how you attribute request
#[PHA\Producer('application/json', 'Json')] //This is how you produce response body from returned value
public function handlePost(ServerRequestInterface $request): \My\DTO
{
$errors = $request->getAttribute('errors');
if (!empty($errors))
{
//This is how you can return non-200 responses
throw new Exception\UnprocessableEntity($errors);
}
/* @var \My\DTO $dto */
$dto = $request->getAttribute('dto');
return $dto;
}
}
Finally, you need to configure special factory for router service. Here is a sample configuration for Laminas Service Manager (example is in YAML just for readability):
dependencies:
factories:
Mezzio\Router\RouterInterface: Articus\PathHandler\RouteInjectionFactory
Articus\PathHandler\MetadataProviderInterface: Articus\PathHandler\MetadataProvider\Factory\PhpAttribute
Articus\PathHandler\Handler\PluginManager: [Articus\PluginManager\Factory\Laminas, Articus\PathHandler\Handler\PluginManager]
Articus\PathHandler\Consumer\PluginManager: Articus\PathHandler\Consumer\Factory\PluginManager
Articus\PathHandler\Attribute\PluginManager: Articus\PathHandler\Attribute\Factory\PluginManager
Articus\PathHandler\Producer\PluginManager: Articus\PathHandler\Producer\Factory\PluginManager
Articus\PathHandler\RouteInjectionFactory:
paths:
'':
# List of your handlers
- My\Handler
# Configuration for handler plugin manager - sub-container dedicated for handlers
Articus\PathHandler\Handler\PluginManager:
factories:
My\Handler: My\HandlerFactory
Production configuration
In production environment you may want to activate persistent handler metadata cache via configuration:
# Cache metadata in single file data/cache/php-attribute-metadata.php
Articus\PathHandler\MetadataProvider\PhpAttribute:
cache:
directory: data/cache
If you use default router you may also want to activate persistent routing table cache:
# Cache routing table in single file data/cache/fast-route.php
Articus\PathHandler\RouteInjectionFactory:
router:
cache:
directory: data/cache
If your application uses some PSR-16 implementation, library can utilize it insteadof simple file caching:
dependencies:
factories:
my_psr16_implementation: My\PSR16ImplementationFactory
Articus\PathHandler\MetadataProvider\PhpAttribute:
cache: my_psr16_implementation
Articus\PathHandler\RouteInjectionFactory:
router:
cache: my_psr16_implementation
Last modified: 24 March 2024