alexlisenkov/uuid-argument-resolver-bundle
Installation:
composer require alexlisenkov/uuid-argument-resolver-bundle
No additional configuration is required for basic usage.
First Use Case:
Inject Ramsey\Uuid\UuidInterface into a Symfony controller or service method. The bundle automatically resolves UUIDs from route parameters (e.g., /{uuid}) or query strings (e.g., ?uuid=...).
use Ramsey\Uuid\UuidInterface;
class UserController
{
public function show(UuidInterface $userId): void
{
// $userId is now a valid UuidInterface instance
}
}
Where to Look First:
Route Parameter Resolution:
Use UUIDs in route paths (e.g., /users/{uuid}) to automatically bind them to UuidInterface arguments:
# config/routes.yaml
show_user:
path: /users/{uuid}
controller: App\Controller\UserController::show
methods: GET
Query String Resolution:
Extract UUIDs from query parameters (e.g., ?uuid=...):
public function search(UuidInterface $filterUuid): void
{
// Resolves from ?uuid=...
}
Service Injection:
Inject UuidInterface into services for UUID handling:
class UserService
{
public function __construct(
private UserRepository $repository,
private UuidInterface $userId // Resolved from route/query
) {}
}
Validation:
The bundle automatically validates UUIDs. Invalid UUIDs trigger a 400 Bad Request by default (customizable, see below).
Custom Types: Extend UuidInterface for domain-specific UUIDs (e.g., UserId):
class UserId implements UuidInterface
{
private Uuid $uuid;
public function __construct(string $uuid)
{
$this->uuid = Uuid::fromString($uuid);
}
// Delegate methods to $this->uuid
}
Use dependency injection to convert resolved UuidInterface to your custom type.
Form Handling:
Use UuidInterface in form request handlers:
public function update(UuidInterface $userId, Request $request): void
{
$data = $request->request->all();
// $userId is validated before processing
}
API Resources:
Return UUIDs in API responses as strings (convert UuidInterface to string):
return $this->json(['id' => $userId->toString()]);
Route Parameter Naming: The bundle resolves UUIDs from route parameters only if the parameter name matches the argument name.
public function show(UuidInterface $id) with route /users/{uuid}.public function show(UuidInterface $uuid) with route /users/{uuid}.Query String Conflicts:
If both a route parameter and query string exist (e.g., /users/{uuid}?uuid=...), the route parameter takes precedence.
Case Sensitivity:
Route parameters are case-sensitive. Use consistent casing (e.g., {uuid} vs {UUID}).
Validation Overhead: The bundle validates UUIDs before the controller/service is instantiated. Avoid heavy logic in constructors if UUID resolution fails.
Invalid UUIDs:
Check the default 400 Bad Request response or your custom factory (if configured). Log the raw input to debug malformed UUIDs:
// In your custom factory
error_log('Invalid UUID received: ' . $request->get('uuid'));
Symfony Debug Toolbar: Use the Argument Resolver tab to inspect resolved arguments and their sources.
Custom Response Factory:
Ensure your factory implements Psr\Http\Message\ResponseInterface and is properly configured in services.yaml:
services:
App\Factory\InvalidUuidResponseFactory: ~
Override the service after defining the factory:
alexlisenkov.uuid_argument_resolver_bundle.uuid_invalid_response:
factory: ['@App\Factory\InvalidUuidResponseFactory', 'create']
Dependency Injection:
The bundle relies on Symfony’s argument resolver. Ensure it’s enabled in config/packages/framework.yaml:
framework:
router:
resource: "%kernel.project_dir%/config/routes.yaml"
type: "yaml"
Custom UUID Types:
Create a compiler pass to transform resolved UuidInterface into domain-specific types:
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class UuidTypeCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->findDefinition('your_service');
$definition->setArgument(0, new Reference('your_uuid_type_factory'));
}
}
Event Listeners:
Listen to kernel.exception to handle invalid UUIDs globally:
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getThrowable();
if ($exception instanceof \InvalidArgumentException && str_contains($exception->getMessage(), 'Invalid UUID')) {
$event->setResponse($this->customInvalidUuidResponse());
}
}
Testing:
Mock UuidInterface in tests:
$mockUuid = $this->createMock(UuidInterface::class);
$mockUuid->method('toString')->willReturn('123e4567-e89b-12d3-a456-426614174000');
$this->container->set('uuid_resolver', $mockUuid);
How can I help you explore Laravel packages today?