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

chamber-orchestra/form-bundle

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require chamber-orchestra/form-bundle

Enable the bundle in config/bundles.php:

return [
    // ...
    ChamberOrchestra\FormBundle\FormBundle::class => ['all' => true],
];
  1. First Use Case: Create a JSON-first API form type for a User entity:

    // src/Form/Type/UserType.php
    namespace App\Form\Type;
    
    use ChamberOrchestra\FormBundle\Type\JsonFormType;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    
    class UserType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options): void
        {
            $builder
                ->add('name', JsonFormType::class, [
                    'json_schema' => [
                        'type' => 'string',
                        'minLength' => 2,
                    ],
                ])
                ->add('email', JsonFormType::class, [
                    'json_schema' => [
                        'type' => 'string',
                        'format' => 'email',
                    ],
                ]);
        }
    }
    
  2. Controller Integration: Use the JsonFormControllerTrait to handle requests:

    // src/Controller/UserController.php
    use ChamberOrchestra\FormBundle\Controller\JsonFormControllerTrait;
    use Symfony\Component\HttpFoundation\JsonResponse;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Routing\Annotation\Route;
    
    class UserController
    {
        use JsonFormControllerTrait;
    
        #[Route('/users', methods: ['POST'])]
        public function create(Request $request): JsonResponse
        {
            return $this->handleJsonFormRequest(
                $request,
                UserType::class,
                'user',
                'user_created'
            );
        }
    }
    
  3. Key Files to Reference:

    • src/Type/JsonFormType.php (core form type logic)
    • src/Transformer/JsonTransformer.php (data transformation)
    • src/Validator/JsonSchemaValidator.php (validation rules)

Implementation Patterns

1. Form Type Patterns

  • JSON Schema Validation: Leverage JsonFormType with embedded JSON Schema for validation:

    $builder->add('address', JsonFormType::class, [
        'json_schema' => [
            'type' => 'object',
            'properties' => [
                'street' => ['type' => 'string'],
                'city' => ['type' => 'string'],
            ],
            'required' => ['street', 'city'],
        ],
    ]);
    
  • Nested Forms: Use JsonFormType recursively for nested objects:

    $builder->add('profile', JsonFormType::class, [
        'json_schema' => ['$ref' => '#/components/schemas/Profile'],
        'mapped' => false, // Opt-out of automatic binding
    ]);
    
  • Custom Transformers: Extend JsonTransformer for domain-specific logic:

    // src/Transformer/CustomUserTransformer.php
    use ChamberOrchestra\FormBundle\Transformer\JsonTransformer;
    
    class CustomUserTransformer extends JsonTransformer
    {
        public function transform($data): array
        {
            if (isset($data['raw_email'])) {
                $data['email'] = strtolower($data['raw_email']);
            }
            return parent::transform($data);
        }
    }
    

    Register in services.yaml:

    services:
        App\Transformer\CustomUserTransformer:
            tags: [chamber_orchestra.form.transformer]
    

2. Controller Workflows

  • Request Handling: Use JsonFormControllerTrait for standardized workflows:

    // Handles POST/PUT/PATCH with automatic:
    // - JSON parsing
    // - Form creation
    // - Validation
    // - Error response (RFC 9457)
    return $this->handleJsonFormRequest(
        $request,
        UserType::class,
        'user', // form name
        'user_updated', // success route
        ['csrf_protection' => false] // options
    );
    
  • Partial Updates: Enable PATCH support via partial option:

    $this->handleJsonFormRequest(
        $request,
        UserType::class,
        'user',
        'user_updated',
        ['partial' => true]
    );
    
  • Error Responses: Customize problem details via error_mapper:

    # config/services.yaml
    services:
        App\Error\CustomProblemDetailsMapper:
            arguments: ['@chamber_orchestra.form.error_mapper.default']
            tags: [chamber_orchestra.form.error_mapper]
    

3. Validation Patterns

  • Doctrine + JSON Schema: Combine constraints:

    use Symfony\Component\Validator\Constraints as Assert;
    
    $builder->add('age', JsonFormType::class, [
        'json_schema' => ['type' => 'integer', 'minimum' => 0],
        'constraints' => [
            new Assert\NotBlank(),
            new Assert\LessThan(150),
        ],
    ]);
    
  • Custom Validators: Extend JsonSchemaValidator:

    // src/Validator/CustomValidator.php
    use ChamberOrchestra\FormBundle\Validator\JsonSchemaValidator;
    
    class CustomValidator extends JsonSchemaValidator
    {
        public function validate($value, Constraint $constraint): void
        {
            if ($value === 'admin') {
                $this->context->addViolation($constraint->message);
            }
            parent::validate($value, $constraint);
        }
    }
    

    Register in services.yaml:

    services:
        App\Validator\CustomValidator:
            tags: [validator.constraint_validator]
    

4. Integration Tips

  • Symfony UX: Pair with symfony/ux for live updates:

    use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
    
    #[AsLiveComponent('user_form')]
    class UserForm extends AbstractType { ... }
    
  • API Platform: Use JsonFormType for input normalization:

    # config/api_platform/resources.yaml
    App\Entity\User:
        input_form: App\Form\Type\UserType
    
  • Messenger: Dispatch events on form submission:

    use ChamberOrchestra\FormBundle\Event\FormSubmittedEvent;
    
    $dispatcher->addListener(FormSubmittedEvent::class, function (FormSubmittedEvent $event) {
        $this->messageBus->dispatch(new UserCreatedEvent($event->getData()));
    });
    

Gotchas and Tips

1. Common Pitfalls

  • Null Handling: JSON Schema defaults to null for missing fields. Explicitly mark required fields:

    'json_schema' => [
        'type' => 'object',
        'required' => ['name'], // Forces presence
    ],
    
  • Circular References: Avoid infinite loops in nested forms. Use mapped: false for non-entity fields:

    $builder->add('metadata', JsonFormType::class, ['mapped' => false]);
    
  • CSRF Protection: Disable for API endpoints (but enable for web forms):

    $this->handleJsonFormRequest(..., ['csrf_protection' => false]);
    
  • Doctrine Events: Clear the FormInterface after submission to avoid stale data:

    $form->submit($data);
    if ($form->isSubmitted() && $form->isValid()) {
        $entity = $form->getData();
        $form->submit(null); // Reset form
    }
    

2. Debugging Tips

  • Validation Errors: Inspect the ProblemDetails object:

    $this->handleJsonFormRequest(..., null, null, null, [
        'error_mapper' => 'custom_mapper',
        'debug' => true, // Logs full error details
    ]);
    
  • Transformer Issues: Override JsonTransformer to log raw input:

    class DebugTransformer extends JsonTransformer
    {
        public function transform($data): array
        {
            error_log('Raw data:', $data);
            return parent::transform($data);
        }
    }
    
  • Schema Validation: Validate schemas independently:

    use ChamberOrchestra\FormBundle\Validator\JsonSchemaValidator;
    
    $validator = new JsonSchemaValidator();
    $validator->validate($data, ['type' => 'object']);
    

3. Configuration Quirks

  • Service Overrides: Prefer tagging over direct service replacement:

    # Override the default transformer
    services:
        ChamberOrchestra\FormBundle\Transformer\JsonTransformer:
            class: App\Transformer\CustomUserTransformer
    
  • JSON Schema Draft: Set the default draft in `config/packages/ch

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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
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