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

Liform Bundle Laravel Package

answear/liform-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require limenius/liform-bundle
    

    Ensure your project uses Symfony 5.4+, 6.x, 7.x, or 8.x.

  2. Enable the Bundle: Add to config/bundles.php (Symfony 5.4+) or AppKernel.php (legacy):

    Limenius\LiformBundle\LimeniusLiformBundle::class => ['all' => true],
    
  3. First Use Case: Transform a Symfony form into JSON Schema in a controller:

    use Symfony\Component\Form\FormFactoryInterface;
    
    class MyController extends AbstractController {
        public function generateSchema(FormFactoryInterface $formFactory): JsonResponse {
            $form = $formFactory->createNamedBuilder('my_form', FormType::class)
                ->add('field', TextType::class)
                ->getForm();
    
            $schema = $this->get('liform')->transform($form);
            return new JsonResponse($schema);
        }
    }
    
  4. Frontend Integration: Use the schema with libraries like liform-react or json-editor. Example API endpoint:

    # config/routes.yaml
    generate_schema:
        path: /api/schema
        controller: App\Controller\MyController::generateSchema
        methods: GET
    

Implementation Patterns

Core Workflow

  1. Form Definition: Define your Symfony form types with metadata (e.g., title, description, attr for UI hints). Example:

    $builder->add('name', TextType::class, [
        'label' => 'Full Name',
        'attr' => ['placeholder' => 'Enter your name'],
        'description' => 'Required field',
    ]);
    
  2. Schema Generation: Inject Limenius\LiformBundle\Liform service and call transform():

    $schema = $this->get('liform')->transform($form);
    
    • Root Forms: Include action (URL) and method (HTTP verb) for form submission.
    • Nested Forms: Automatically handles collections (CollectionType) and embedded forms.
  3. Frontend Synchronization:

    • Initial Values: Serialize form data for pre-filling:
      $initialData = $this->get('serializer')->normalize($form->createView());
      
    • Validation Errors: Normalize errors for frontend display:
      $errors = $this->get('serializer')->normalize($form);
      
  4. API-Driven Forms: Expose schemas via API endpoints (e.g., /api/forms/{type}/schema) and use them to:

    • Dynamically generate forms in React/Vue.
    • Validate client-side submissions against the schema.

Integration Tips

  1. Symfony UX Integration: Combine with Symfony UX (e.g., Turbo/Stimulus) for reactive forms:

    // Frontend (liform-react)
    <JsonEditor
      schema={schemaFromApi}
      onChange={handleFormChange}
      error={formErrors}
    />
    
  2. Dynamic Schema Updates: Regenerate schemas on-the-fly for dynamic forms (e.g., conditional fields):

    // Controller
    $form = $this->createForm(DynamicFormType::class, $data, [
        'conditional_fields' => $request->query->get('fields'),
    ]);
    $schema = $this->get('liform')->transform($form);
    
  3. Caching: Cache generated schemas (e.g., with Symfony Cache component) to avoid reprocessing:

    $cacheKey = 'form_schema_' . md5($formTypeClass);
    $schema = $this->get('liform.cache')->get($cacheKey, function() use ($form) {
        return $this->get('liform')->transform($form);
    });
    
  4. Testing: Test schemas against expected JSON structures:

    $schema = $this->get('liform')->transform($form);
    $this->assertJsonStringEqualsJsonString(
        file_get_contents(__DIR__.'/expected_schema.json'),
        json_encode($schema)
    );
    

Gotchas and Tips

Pitfalls

  1. CSRF Protection: Disable CSRF for API forms to avoid schema bloat:

    $form = $this->createForm(FormType::class, $data, ['csrf_protection' => false]);
    
    • Warning: Only disable CSRF for trusted APIs or use tokens separately.
  2. Circular References: Avoid circular references in form types (e.g., self-referential collections) as they may cause infinite loops during schema generation.

  3. Symfony 6+ Changes:

    • Form Types: Use FormBuilderInterface (not FormFactoryInterface) for newer Symfony versions.
    • Dependency Injection: Prefer autowiring over manual service lookup.
  4. Schema Validation: Liform generates schemas but doesn’t validate them. Use tools like ajv on the frontend to enforce schema rules.


Debugging

  1. Transformer Issues: If a form field isn’t rendered correctly, check:

    • The block_prefix of the form type (e.g., Symfony\Component\Form\Extension\Core\Type\TextTypetext).
    • Custom transformers registered for the type (see Usage).
  2. Extensions Not Applying: Ensure extensions are tagged correctly in services.yaml:

    services:
        app.liform.my_extension:
            class: App\Liform\MyExtension
            tags:
                - { name: liform.extension, priority: 100 } # Priority affects order
    
  3. Initial Data Mismatch: Verify that form data matches the schema structure. Use:

    $view = $form->createView();
    $data = $this->get('serializer')->normalize($view);
    dump($data); // Debug shape
    

Extension Points

  1. Custom Transformers: Extend default behavior for specific form types (e.g., ChoiceType):

    // src/Liform/CustomChoiceTransformer.php
    class CustomChoiceTransformer extends AbstractTransformer {
        public function transformField(FieldInterface $field, FormInterface $form): array {
            $schema = parent::transformField($field, $form);
            $schema['choices'] = $form->getConfig()->getOption('choices');
            return $schema;
        }
    }
    

    Register in services.yaml:

    services:
        app.liform.choice_transformer:
            class: App\Liform\CustomChoiceTransformer
            tags:
                - { name: liform.transformer, form_type: choice }
    
  2. Global Extensions: Modify all schemas (e.g., add metadata):

    class GlobalExtension implements ExtensionInterface {
        public function apply(FormInterface $form, array $schema): array {
            $schema['metadata'] = [
                'version' => '1.0',
                'author' => 'Your Name',
            ];
            return $schema;
        }
    }
    
  3. Conditional Logic: Use extensions to add dynamic properties:

    class ConditionalExtension implements ExtensionInterface {
        public function apply(FormInterface $form, array $schema): array {
            if ($form->has('is_active') && $form->get('is_active')->getConfig()->getOption('required')) {
                $schema['required'][] = 'is_active';
            }
            return $schema;
        }
    }
    

Configuration Quirks

  1. Symfony 8+: Use config/packages/liform.yaml for bundle config (if available). Example:

    limenius_liform:
        default_options:
            ignore_unknown_fields: true # Skip fields without transformers
    
  2. Performance: Disable debug mode for production to avoid schema regeneration on every request:

    $this->container->get('liform')->setDebug(false);
    
  3. Frontend Compatibility: Ensure your frontend library supports the generated schema. For liform-react, use:

    <JsonEditor
      schema={schema}
      theme="bootstrap3"
      show_errors={true}
    />
    

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