Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Request Mapper Laravel Package

devouted/request-mapper

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require devouted/request-mapper
    

    Ensure your project meets the requirements (PHP ≥ 8.2, Symfony 6.4+).

  2. First Use Case: Create a DTO (Data Transfer Object) with annotated constructor parameters. Example:

    use RequestMapper\Attribute\FromQuery;
    
    class CreateUserRequest
    {
        public function __construct(
            #[FromQuery]
            public string $name,
            #[FromQuery]
            public string $email,
        ) {}
    }
    
  3. Integration: Register the RequestMapper service in your Symfony kernel or DI container:

    // config/services.yaml
    services:
        RequestMapper\Serializer\Denormalizer\RequestMapperDenormalizer:
            tags: [serializer.normalizer]
    
  4. Usage in Controller:

    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Serializer\SerializerInterface;
    
    public function createUser(Request $request, SerializerInterface $serializer)
    {
        $dto = $serializer->deserialize($request, CreateUserRequest::class, 'request_mapper');
        // Use $dto->name, $dto->email...
    }
    

Implementation Patterns

Common Workflows

  1. Request Parameter Mapping: Use attributes (FromQuery, FromHeader, FromPath, FromUploads) to map request data to DTO properties.

    class UpdateProfileRequest
    {
        public function __construct(
            #[FromQuery(name: 'page')]
            public int $page = 1,
            #[FromHeader(name: 'X-API-Key')]
            public string $apiKey,
        ) {}
    }
    
  2. Nested Objects: Combine with Symfony’s Serializer to handle nested DTOs.

    class UserProfile
    {
        public function __construct(
            #[FromQuery]
            public string $bio,
            #[FromQuery]
            public Address $address,
        ) {}
    }
    
    class Address
    {
        public function __construct(
            #[FromQuery]
            public string $street,
        ) {}
    }
    
  3. File Uploads: Map uploaded files to properties.

    class UploadMediaRequest
    {
        public function __construct(
            #[FromUploads]
            public array $images = [],
            #[FromPath]
            public int $albumId,
        ) {}
    }
    
  4. Validation Integration: Pair with Symfony’s Validator for runtime validation.

    use Symfony\Component\Validator\Constraints as Assert;
    
    class LoginRequest
    {
        #[FromQuery]
        #[Assert\NotBlank]
        public string $username;
    
        #[FromQuery]
        #[Assert\NotBlank]
        public string $password;
    }
    
  5. Custom Formatters: Extend the package by creating custom formatters for non-standard request sources.

    use RequestMapper\Formatter\FormatterInterface;
    
    class CustomHeaderFormatter implements FormatterInterface
    {
        public function format($value, string $name, array $context): mixed
        {
            return strtoupper($value);
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Attribute Order Matters: If multiple attributes target the same source (e.g., FromQuery and FromHeader for the same parameter), the last declared attribute in the constructor takes precedence.

  2. Missing Parameters: Unmapped parameters in the request (e.g., a required FromQuery field missing) will throw a DenormalizationException. Handle gracefully with default values or custom exception handling.

  3. File Uploads: FromUploads expects files to be in the files key of the request. For custom file keys, use a custom formatter:

    #[FromUploads(key: 'custom_files')]
    public array $files;
    
  4. Symfony Serializer Conflict: Ensure the RequestMapperDenormalizer is registered after the default Symfony denormalizers to avoid conflicts.

  5. PHP 8.2+ Features: Leverage PHP 8.2+ features like read-only properties for immutable DTOs:

    class ImmutableRequest
    {
        public function __construct(
            #[FromQuery]
            public readonly string $name,
        ) {}
    }
    

Debugging

  • Enable Serializer Debug: Add this to config/packages/serializer.yaml to debug deserialization:
    framework:
        serializer:
            debug: true
    
  • Check Context: The RequestMapperDenormalizer passes the request object as context. Access it via:
    $request = $context['request'];
    

Tips

  1. Reuse DTOs: Create reusable DTOs for common request patterns (e.g., PaginationRequest, AuthRequest).

  2. Type Safety: Use PHP 8.1+ union types or null defaults for optional fields:

    #[FromQuery]
    public string|null $optionalField = null;
    
  3. Testing: Mock the Request object in tests:

    $request = new Request([], [], ['HTTP_ACCEPT_LANGUAGE' => 'en']);
    $dto = $serializer->deserialize($request, GetArticleQuery::class, 'request_mapper');
    
  4. Performance: For high-traffic APIs, cache serialized DTOs if the request structure is static.

  5. Extending Attributes: Create custom attributes by extending RequestMapper\Attribute\AbstractAttribute:

    #[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_PARAMETER)]
    class FromCookie extends AbstractAttribute
    {
        public function getSource(): string
        {
            return 'cookie';
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor