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 Resolver Bundle Laravel Package

codingculture/request-resolver-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require codingculture/request-resolver-bundle
    

    Ensure CodingCulture\RequestResolverBundle\RequestResolverBundle is enabled in config/bundles.php.

  2. First Use Case: Basic Request Validation Create a request class implementing ResolvableRequestInterface:

    use CodingCulture\RequestResolverBundle\Request\ResolvableRequestInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    
    final class CreateUserRequest implements ResolvableRequestInterface
    {
        private $options = [];
    
        public function getName(): string
        {
            return $this->options['name'];
        }
    
        public function defineOptions(OptionsResolver $resolver): void
        {
            $resolver->setDefaults([
                'name' => null,
            ])
            ->setRequired(['name'])
            ->setAllowedTypes('name', 'string');
        }
    }
    
  3. Resolve in Controller Inject and use the resolver:

    use CodingCulture\RequestResolverBundle\Resolver\RequestResolver;
    use Symfony\Component\HttpFoundation\Request;
    
    class UserController extends AbstractController
    {
        public function create(RequestResolver $resolver, Request $request)
        {
            $userRequest = $resolver->resolve(new CreateUserRequest(), $request->request->all());
            $name = $userRequest->getName(); // Safe access after validation
        }
    }
    

Implementation Patterns

Workflows

  1. Request Validation in Controllers Replace manual validation with resolved requests:

    public function update(RequestResolver $resolver, Request $request, int $id)
    {
        $updateRequest = $resolver->resolve(new UpdateUserRequest(), $request->all());
        $user = $this->userRepository->find($id);
        $user->update($updateRequest->getName(), $updateRequest->getEmail());
    }
    
  2. Nested Requests For complex payloads, nest requests:

    final class CreateOrderRequest implements ResolvableRequestInterface
    {
        public function defineOptions(OptionsResolver $resolver): void
        {
            $resolver->setDefaults([
                'items' => [],
            ])
            ->setAllowedTypes('items', 'array')
            ->setNormalizer('items', function ($items) {
                return array_map(fn ($item) => $resolver->resolve(new OrderItemRequest(), $item), $items);
            });
        }
    }
    
  3. Service Integration Pass resolved requests to services:

    public function checkout(RequestResolver $resolver, Request $request)
    {
        $checkoutRequest = $resolver->resolve(new CheckoutRequest(), $request->all());
        $this->checkoutService->process($checkoutRequest);
    }
    

Integration Tips

  • Form Integration: Use with Symfony Forms for type safety:
    $form = $this->createForm(CreateUserType::class);
    $form->submit($request->request->all());
    if ($form->isSubmitted() && $form->isValid()) {
        $userRequest = $resolver->resolve(new CreateUserRequest(), $form->getData());
    }
    
  • API Resources: Validate API payloads before processing:
    $apiRequest = $resolver->resolve(new ApiRequest(), json_decode($request->getContent(), true));
    

Gotchas and Tips

Pitfalls

  1. Type Safety

    • The resolver does not cast types automatically. Use setNormalizer or setAllowedTypes explicitly:
      $resolver->setAllowedTypes('age', 'int')
               ->setNormalizer('age', fn ($value) => (int) $value);
      
  2. Circular References

    • Avoid circular dependencies in nested requests. Use setDefault with callables for lazy resolution:
      $resolver->setDefaults([
          'parent' => fn ($options) => $resolver->resolve(new ParentRequest(), $options['parent_data']),
      ]);
      
  3. Error Handling

    • Resolver throws InvalidArgumentException on invalid data. Catch and handle gracefully:
      try {
          $request = $resolver->resolve(new SomeRequest(), $data);
      } catch (InvalidArgumentException $e) {
          return new JsonResponse(['error' => $e->getMessage()], 400);
      }
      

Debugging

  • Enable Symfony Debug Toolbar: Inspect resolved options via the "Request" tab.
  • Log Resolver Output: Temporarily add logging to defineOptions:
    $resolver->setDefaults(function (OptionsResolver $r) {
        \Log::debug('Resolver defaults:', $r->getDefaults());
    });
    

Extension Points

  1. Custom Resolver Extend RequestResolver for global logic:

    class CustomResolver extends RequestResolver
    {
        protected function configureOptions(OptionsResolver $resolver): void
        {
            $resolver->setNormalizer('timestamp', fn ($value) => strtotime($value));
        }
    }
    

    Bind in services.yaml:

    services:
        CodingCulture\RequestResolverBundle\Resolver\RequestResolver: '@app.custom_resolver'
    
  2. Dynamic Option Resolution Use setNormalizer for runtime transformations:

    $resolver->setNormalizer('user', fn ($id) => $this->userRepository->find($id));
    
  3. Validation Groups Leverage Symfony Validator for complex rules:

    use Symfony\Component\Validator\Constraints as Assert;
    
    $resolver->setDefaults([
        'email' => null,
    ])
    ->setAllowedTypes('email', ['string', 'null'])
    ->setNormalizer('email', fn ($email) => $this->validator->validate($email, [
        new Assert\Email(),
        new Assert\NotBlank(),
    ]));
    
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.
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver