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

symfony/form

Symfony Form component helps you build, process, validate, and reuse HTML forms with a robust, extensible API. Includes field types, data mapping, CSRF protection, and integration hooks for Symfony apps or standalone PHP projects.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Installation:

    composer require symfony/form
    

    Laravel already includes Symfony’s Form component, so no additional configuration is needed.

  2. First Use Case: Create a simple form for a User model in a controller:

    use Symfony\Component\Form\Extension\Core\Type\TextType;
    use Symfony\Component\Form\Extension\Core\Type\SubmitType;
    use Symfony\Component\Form\FormBuilderInterface;
    
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class)
            ->add('save', SubmitType::class);
    }
    
  3. Rendering in Blade:

    {!! Form::open(['route' => 'users.store']) !!}
        {!! $form->text('name') !!}
        {!! $form->submit('Save') !!}
    {!! Form::close() !!}
    

    (Use collect($form->all()) to render fields dynamically.)

  4. Handling Submission:

    $form = $this->createForm(UserType::class, $user);
    $form->handleRequest($request);
    
    if ($form->isSubmitted() && $form->isValid()) {
        $user = $form->getData();
        // Save to DB
    }
    

Key Starting Points

  • Documentation: Symfony Form Component
  • Laravel Integration: Use Form::create() helper or inject FormFactoryInterface.
  • Common Types: TextType, EmailType, ChoiceType, CollectionType (for nested forms).

Implementation Patterns

1. Form Types and Reusability

  • Create Custom Types:
    namespace App\Form;
    
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    
    class UserType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('email')
                ->add('password', PasswordType::class);
        }
    }
    
  • Reuse Types: Extend AbstractType for domain-specific forms (e.g., ProductType, OrderType).

2. Data Binding and Validation

  • Bind to Entities:
    $form = $this->createForm(UserType::class, $existingUser);
    
  • Validation: Use Symfony’s Validator component (included in Laravel) with attributes:
    use Symfony\Component\Validator\Constraints as Assert;
    
    class User
    {
        #[Assert\Email]
        public string $email;
    }
    

3. Dynamic Forms

  • Collection Types (for lists/arrays):
    $builder->add('tags', CollectionType::class, [
        'entry_type' => TextType::class,
        'allow_add'   => true,
        'allow_delete' => true,
        'by_reference' => false,
    ]);
    
  • Entity Types (for dropdowns):
    $builder->add('role', EntityType::class, [
        'class' => Role::class,
        'choice_label' => 'name',
    ]);
    

4. Multi-Step Forms (Laravel + FormFlow)

  • Laravel Workflow: Use FormFlow (v8+) with session storage:
    use Symfony\Component\Form\FormFlow;
    
    $flow = new FormFlow();
    $flow->addStep('step1', new UserType());
    $flow->addStep('step2', new AddressType());
    
    $form = $flow->createForm();
    $form->handleRequest($request);
    
    if ($flow->isFinished()) {
        $data = $flow->getData();
    }
    
  • Session Handling: Configure session.storage.handler in config/session.php to avoid serialization issues.

5. Twig Integration

  • Render Forms:
    {{ form_start(form) }}
        {{ form_row(form.name) }}
        {{ form_errors(form) }}
    {{ form_end(form) }}
    
  • Custom Templates: Override resources/views/vendor/form/fields.html.twig for global styling.

6. CSRF and Security

  • CSRF Protection: Enabled by default in Laravel. Use Form::open() with routes:
    Form::open(['route' => 'users.store']);
    
  • Honeypot Fields: Add hidden fields to combat bots:
    $builder->add('website', HiddenType::class, ['attr' => ['class' => 'honeypot']]);
    

7. File Uploads

  • FileType:
    $builder->add('avatar', FileType::class, [
        'label' => 'Profile Picture',
        'mapped' => false, // Handle manually
    ]);
    
  • Validation:
    #[Assert\File(mimeTypes: {'image/jpeg', 'image/png'})]
    public ?UploadedFile $avatar;
    

8. Testing Forms

  • Unit Tests:
    use Symfony\Component\Form\Test\TypeTestCase;
    
    class UserTypeTest extends TypeTestCase
    {
        public function testSubmitValidData()
        {
            $formData = ['name' => 'John'];
            $form = $this->factory->create(UserType::class);
            $form->submit($formData);
            $this->assertTrue($form->isSubmitted());
            $this->assertEquals($formData, $form->getData());
        }
    }
    
  • Feature Tests: Use Laravel’s actingAs() and post() to test form submissions.

Gotchas and Tips

Common Pitfalls

  1. Session Serialization Errors:

    • Issue: Non-serializable objects (e.g., Doctrine entities with lazy collections) break FormFlow.
    • Fix: Use by_reference: true or implement __serialize()/__unserialize():
      public function __serialize(): array { return ['data']; }
      public function __unserialize(array $data): void { $this->data = $data['data']; }
      
  2. Mismatched Indices in Collections:

    • Issue: POST data with mismatched indices (e.g., tags[0][name] vs. tags[1][name]) causes data loss.
    • Fix: Use allow_add: true and prototype: true:
      $builder->add('tags', CollectionType::class, [
          'prototype' => true,
          'entry_options' => ['label' => false],
      ]);
      
  3. CSRF Token Mismatch:

    • Issue: Token errors when forms are submitted via AJAX or nested in iframes.
    • Fix: Regenerate tokens on AJAX requests or use Form::createView():
      $formView = $form->createView();
      return response()->json(['csrf_token' => $formView->vars['csrf_token']]);
      
  4. Validation Overrides:

    • Issue: Custom validation logic conflicts with Symfony’s constraints.
    • Fix: Use pre_set_data or post_set_data callbacks:
      $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
          $data = $event->getData();
          if ($data && $data->isActive()) {
              $event->getForm()->add('status', HiddenType::class, ['data' => 'active']);
          }
      });
      
  5. DateTime Handling:

    • Issue: Timezone mismatches or invalid dates.
    • Fix: Configure DateTimeType:
      $builder->add('birthday', DateType::class, [
          'widget' => 'single_text',
          'html5' => true,
          'attr' => ['class' => 'datepicker'],
      ]);
      
  6. Performance with Large Forms:

    • Issue: Slow rendering or submission for forms with 50+ fields.
    • Fix:
      • Use FormTheme to reduce template complexity.
      • Lazy-load fields with FormEvents::PRE_SUBMIT.

Debugging Tips

  • Dump Form Data:

    dd($form->getData(), $form->getErrors(true), $form->getNormData());
    
  • Enable Debug Toolbar: Symfony’s Profiler shows form variables and submitted data.

  • Check Submitted Values:

    $request->request->all(); // GET/POST data
    $request->files->all();   // File uploads
    

Extension Points

  1. Custom Data Transformers:
    use Symfony\Component\Form\DataTransformerInterface;
    
    class SlugTransformer implements DataTransformerInterface
    {
        public function transform($value): ?string
        {
            return Str::slug($value);
        }
        public function reverseTransform($value): string
        {
            return Str::title($value);
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4