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

Form Request Bundle Laravel Package

adamsafr/form-request-bundle

Symfony bundle bringing Laravel-style Form Requests: create custom request classes with validation rules that run before controller actions. Simple install via Composer/Flex, optional JSON error listeners for access denied, validation and JSON decode failures.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require adamsafr/form-request-bundle
    

    Enable the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (older versions):

    Adamsafr\FormRequestBundle\AdamsafrFormRequestBundle::class => ['all' => true],
    
  2. Create a Form Request Class: Extend Adamsafr\FormRequestBundle\Request\FormRequest and define validation rules in the rules() method:

    namespace App\Request;
    
    use Adamsafr\FormRequestBundle\Request\FormRequest;
    
    class StoreUserRequest extends FormRequest
    {
        public function rules()
        {
            return [
                'name' => 'required|string|max:255',
                'email' => 'required|email',
            ];
        }
    }
    
  3. Use in Controller: Inject the request class into your controller action:

    use App\Request\StoreUserRequest;
    use Symfony\Component\HttpFoundation\Request;
    
    public function store(StoreUserRequest $request)
    {
        // Validation is automatically run; $request->isValid() checks status
        $data = $request->validated(); // Returns validated data
        // ...
    }
    

First Use Case

Replace a standard Request object in a controller with a custom FormRequest to centralize validation logic. For example, replace:

public function create(Request $request)
{
    $this->validate($request, [
        'name' => 'required',
        'email' => 'email',
    ]);
    // ...
}

with:

public function create(StoreUserRequest $request)
{
    $data = $request->validated(); // Already validated
    // ...
}

Implementation Patterns

Usage Patterns

  1. Centralized Validation: Move validation logic from controllers to dedicated FormRequest classes. Example:

    class UpdateProfileRequest extends FormRequest
    {
        public function rules()
        {
            return [
                'avatar' => 'nullable|image|mimes:jpeg,png|max:2048',
                'bio' => 'nullable|string|max:500',
            ];
        }
    }
    
  2. Authorization: Override authorize() to gate access:

    public function authorize()
    {
        return $this->user()->isAdmin(); // Assume $this->user() is available
    }
    
  3. Custom Validation Logic: Use validateCustomRules() for complex rules:

    public function rules()
    {
        return [
            'password' => ['required', [$this, 'validatePasswordStrength']],
        ];
    }
    
    public function validatePasswordStrength($attribute, $value, $fail)
    {
        if (!preg_match('/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/', $value)) {
            $fail('Password must be at least 8 characters with uppercase, lowercase, and a number.');
        }
    }
    
  4. Dependency Injection: Inject services into FormRequest via constructor:

    public function __construct(
        private UserRepository $userRepository,
        private LoggerInterface $logger
    ) {}
    
    public function rules()
    {
        return [
            'email' => ['required', [$this->userRepository, 'isEmailAvailable']],
        ];
    }
    
  5. Reusable Requests: Extend base FormRequest for shared validation (e.g., BaseApiRequest for API-wide rules).

Workflows

  1. API Development: Use FormRequest for API endpoints to handle validation before reaching controllers:

    // src/Controller/UserController.php
    public function store(CreateUserRequest $request)
    {
        $user = User::create($request->validated());
        return new JsonResponse(['user' => $user], 201);
    }
    
  2. Form Handling: Combine with Symfony’s Form component for hybrid validation:

    public function update(UpdateProfileRequest $request, User $user)
    {
        $form = $this->createForm(ProfileType::class, $user);
        $form->submit($request->request->all());
    
        if ($form->isSubmitted() && $form->isValid()) {
            $user->update($form->getData());
        }
    }
    
  3. Testing: Mock FormRequest in tests:

    $request = $this->createMock(StoreUserRequest::class);
    $request->method('isValid')->willReturn(true);
    $request->method('validated')->willReturn(['name' => 'Test']);
    $this->controller->store($request);
    

Integration Tips

  1. Symfony Event Dispatcher: Listen to kernel.request to log validation failures:

    $event->getRequest()->addListener(
        FormRequest::EVENT_VALIDATION_FAILED,
        [$this->logger, 'logValidationFailure']
    );
    
  2. Custom Error Responses: Override handleValidationError() in FormRequest:

    protected function handleValidationError($errors)
    {
        return new JsonResponse(['errors' => $errors], 422);
    }
    
  3. Localization: Use Symfony’s translation system for validation messages:

    public function rules()
    {
        return [
            'name' => 'required|string',
        ];
    }
    
    public function messages()
    {
        return [
            'name.required' => 'This field is required.',
        ];
    }
    
  4. Dynamic Rules: Generate rules based on runtime conditions:

    public function rules()
    {
        $rules = ['email' => 'required|email'];
        if ($this->user()->isAdmin()) {
            $rules['role'] = 'required|in:admin,user';
        }
        return $rules;
    }
    

Gotchas and Tips

Pitfalls

  1. Kernel Version Mismatch: The bundle was last updated in 2020 and may not support newer Symfony versions (e.g., 6.x). Test thoroughly or fork the package if needed.

  2. Request Object Override: The bundle replaces Symfony’s default Request object with its own. Ensure middleware/services expecting Request are compatible:

    // Avoid this if using the bundle:
    $request = $this->get('request_stack')->getCurrentRequest();
    // Use FormRequest instead.
    
  3. Validation Timing: Validation runs before the controller action. Avoid relying on $request->request->all() before validation—use $request->validated() or $request->get() for raw data.

  4. Circular Dependencies: Avoid injecting controllers or other FormRequest classes into each other to prevent circular references.

  5. Flex Recipes: If using Symfony Flex, the bundle may not auto-configure. Manually enable it in config/bundles.php:

    return [
        // ...
        Adamsafr\FormRequestBundle\AdamsafrFormRequestBundle::class => ['all' => true],
    ];
    

Debugging

  1. Validation Errors: Check $request->errors() for validation messages:

    if (!$request->isValid()) {
        return new Response($request->errors()->first(), 400);
    }
    
  2. Authorization Failures: Override handleAuthorizationError() to customize responses:

    protected function handleAuthorizationError()
    {
        return new JsonResponse(['error' => 'Unauthorized'], 403);
    }
    
  3. Logging: Enable debug mode to see validation traces:

    $this->container->get('debug')->addErrorCollector(new ValidationErrorCollector());
    

Config Quirks

  1. Bundle Disabling: Set 'all' => false in bundles.php to disable the bundle globally (not recommended for intended use).

  2. Custom Event Names: The bundle uses Adamsafr\FormRequestBundle\Request\FormRequest::EVENT_VALIDATION_FAILED. Override in subclasses if needed:

    const EVENT_CUSTOM_VALIDATION = 'custom.validation.event';
    
  3. Request Stack: The bundle modifies Symfony’s request_stack. Ensure no other bundles interfere with request resolution.

Extension Points

  1. Custom Validators: Create a validator class and attach it to rules:

    $validator = new UniqueUsernameValidator();
    $rules['username'] = [$validator, 'validate'];
    
  2. Request Factories: Extend FormRequestFactory to customize request creation:

    $factory = new CustomFormRequestFactory($container);
    $request = $factory->create(StoreUserRequest::class);
    
  3. Middleware Integration: Use the bundle’s events to trigger middleware logic:

    $dispatcher->addListener(
        FormRequest::EVENT_VALIDATED,
        [$middleware, 'onValidatedRequest']
    );
    
  4. API Platform: Combine with API Platform for automatic request validation:

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