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

ansien/form-to-json-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation: Add the bundle via Composer:

    composer require ansien/form-to-json-bundle
    

    No additional configuration is required—it auto-registers with Symfony’s dependency injection.

  2. First Use Case: Inject FormTransformerInterface into a controller/service and call transform() on a Symfony FormInterface:

    use Ansien\FormToJsonBundle\Transformer\Service\FormTransformerInterface;
    
    public function __construct(private FormTransformerInterface $formTransformer) {}
    
    public function index(): JsonResponse {
        $form = $this->createForm(YourType::class);
        return new JsonResponse($this->formTransformer->transform($form));
    }
    
  3. Key Files:

    • Transformer Service: src/Transformer/Service/FormTransformer.php (core logic).
    • Type Transformers: Located in src/Transformer/Type/ (e.g., TextTypeTransformer, CollectionTypeTransformer).
    • Normalizers: src/Normalizer/ for handling values/errors.

Implementation Patterns

Core Workflow

  1. Form Creation: Build your Symfony form as usual (e.g., createForm(YourType::class, $entity)). The bundle handles nested forms (e.g., CollectionType, FormType) recursively.

  2. Transformation:

    $json = $this->formTransformer->transform($form);
    

    Output includes:

    • schema: Form structure (fields, validation rules, labels).
    • values: Current form data (normalized via ValueNormalizer).
    • errors: Validation errors (normalized via ErrorNormalizer).
  3. API Integration: Return the JSON directly in a JsonResponse or use it to:

    • Pre-fill forms client-side (e.g., React/Vue).
    • Generate dynamic schemas for libraries like JSON Schema.
    • Validate submissions against the schema.

Advanced Patterns

1. Custom Field Normalization

Override value/error normalization for specific fields:

// src/Normalizer/CustomValueNormalizer.php
use Ansien\FormToJsonBundle\Normalizer\ValueNormalizerInterface;

class CustomValueNormalizer implements ValueNormalizerInterface {
    public function normalize($value, FormView $view): ?string {
        if ($view->getName() === 'special_field') {
            return strtoupper($value); // Custom logic
        }
        return $value;
    }
}

Register it as a service with the form_to_json_bundle.value_normalizer tag.

2. Excluding Fields

Use the exclude option in your form type:

$builder->add('field_to_exclude', TextType::class, [
    'form_to_json_bundle' => ['exclude' => true],
]);

3. Dynamic Schema Generation

Generate schemas for forms dynamically (e.g., for a CMS):

$schema = $this->formTransformer->transform($form)['schema'];
$this->serializer->serialize($schema, 'json');

4. Integration with API Platform

Use the bundle to expose form schemas in API Platform’s getCollectionOperations() or getItemOperations():

# config/api_platform/resources.yaml
App\Entity\YourEntity:
    collectionOperationNames: ['get', 'post']
    itemOperationNames: ['get', 'put', 'patch']
    attributes:
        collection:
            operationType: 'get'
            method: 'GET'
            path: '/schemas/your-entity'
            normalization_context:
                groups: ['form_schema']

5. Testing

Mock the transformer in tests:

$form = $this->createForm(YourType::class);
$transformer = $this->createMock(FormTransformerInterface::class);
$transformer->method('transform')->willReturn(['schema' => [], 'values' => []]);

Gotchas and Tips

Pitfalls

  1. Circular References:

    • Forms with circular references (e.g., self-referencing EntityType) may cause infinite recursion.
    • Fix: Use max_depth in the transformer options:
      $this->formTransformer->transform($form, ['max_depth' => 2]);
      
  2. ChoiceType Handling:

    • By default, ChoiceType fields include all choices in the schema, which can bloat JSON.
    • Tip: Use choice_loader to lazy-load choices or filter them:
      $builder->add('field', ChoiceType::class, [
          'choices' => $this->choiceLoader->loadChoices(),
      ]);
      
  3. Translation Domain:

    • Labels/help texts use the form’s translation_domain. Ensure your translator is configured:
      # config/packages/translation.yaml
      framework:
          translator:
              paths: ['%kernel.project_dir%/translations']
              default_path: '%kernel.project_dir%/translations'
      
  4. Deprecated Symfony Features:

    • The bundle targets Symfony 5.2+. If using older versions, check for compatibility gaps (e.g., FormView changes in Symfony 6+).

Debugging Tips

  1. Inspect Raw FormView: Dump the raw FormView before transformation to debug:

    dump($form->createView());
    
  2. Enable Debug Mode: Set FORM_TO_JSON_DEBUG env var to true to log transformer steps:

    export FORM_TO_JSON_DEBUG=true
    
  3. Check Normalizers: Override ValueNormalizer/ErrorNormalizer to log values:

    class DebugValueNormalizer implements ValueNormalizerInterface {
        public function normalize($value, FormView $view): ?string {
            error_log(sprintf(
                'Normalizing %s: %s',
                $view->getName(),
                print_r($value, true)
            ));
            return $value;
        }
    }
    

Extension Points

  1. Custom Type Transformers: Extend AbstractTypeTransformer for unsupported form types (e.g., Symfony\Component\Form\Extension\Core\Type\CustomType):

    class CustomTypeTransformer extends AbstractTypeTransformer {
        public function transform(FormView $view): array {
            return [
                'type' => 'custom',
                'data' => $view->vars['custom_data'],
            ];
        }
    }
    

    Tag the service:

    services:
        App\Transformer\CustomTypeTransformer:
            tags: { name: form_to_json_bundle.type_transformer }
    
  2. Modify Schema Structure: Override the root transformer (FormTransformer) to customize the output format:

    class CustomFormTransformer extends FormTransformer {
        protected function buildSchema(FormView $view): array {
            return [
                'id' => $view->getName(),
                'fields' => $this->transformChildren($view),
            ];
        }
    }
    
  3. Add Metadata: Attach custom metadata to fields via form options:

    $builder->add('field', TextType::class, [
        'form_to_json_bundle' => [
            'metadata' => ['client_id' => 'unique_id_123'],
        ],
    ]);
    

    Access it in your transformer:

    $metadata = $view->vars['form_to_json_bundle']['metadata'] ?? [];
    

Performance Considerations

  1. Avoid Transforming Large Forms: For forms with many fields (e.g., >100), use max_depth or exclude unnecessary fields.

  2. Cache Transformers: If generating schemas repeatedly (e.g., in a loop), cache the transformer instance:

    $transformer = $container->get(FormTransformerInterface::class);
    $cacheKey = md5($form->getName());
    if (!$cachedSchema = $cache->get($cacheKey)) {
        $cachedSchema = $transformer->transform($form);
        $cache->set($cacheKey, $cachedSchema, 3600);
    }
    
  3. Lazy-Load Choices: For ChoiceType with large datasets, use a ChoiceLoader to fetch choices on-demand:

    $builder->add('field', ChoiceType::class, [
        'choice_loader' => $this->choiceLoader,
    ]);
    

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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope