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

Json Schema Form Bundle Laravel Package

cyve/json-schema-form-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle

    composer require cyve/json-schema-form-bundle
    

    Ensure Cyve\JsonSchemaFormBundle\CyveJsonSchemaFormBundle::class is registered in config/bundles.php.

  2. Define a JSON Schema Create a schema file (e.g., config/schema/product.json) or define it inline:

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "Product",
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "price": { "type": "number", "minimum": 0 }
      },
      "required": ["name"]
    }
    
  3. Generate a Form

    use Cyve\JsonSchemaFormBundle\Form\Type\SchemaType;
    use Cyve\JsonSchemaFormBundle\Validator\Constraint\Schema;
    
    $schema = json_decode(file_get_contents('config/schema/product.json'));
    $form = $this->createForm(SchemaType::class, $product, [
        'data_schema' => $schema,
        'constraints' => [new Schema($schema)],
    ]);
    

First Use Case: Dynamic Admin Forms

Use this bundle to dynamically generate forms for admin panels (e.g., EasyAdmin, SonataAdmin) where schemas are stored in the database or config files. Example:

// In a controller or admin class
$form = $this->createFormBuilder($entity)
    ->add('dynamic_form', SchemaType::class, [
        'data_schema' => $this->getSchemaFromDatabase($entityType),
    ])
    ->getForm();

Implementation Patterns

Schema-Driven Form Workflows

  1. Centralized Schema Management Store schemas in YAML/JSON files (e.g., config/schemas/) or fetch them dynamically from an API. Use a service to load schemas:

    // src/Service/SchemaLoader.php
    class SchemaLoader
    {
        public function load(string $schemaPath): object
        {
            return json_decode(file_get_contents($schemaPath));
        }
    }
    
  2. Reusable Form Types Extend SchemaType to add custom logic (e.g., default values, custom validation):

    use Cyve\JsonSchemaFormBundle\Form\Type\SchemaType as BaseSchemaType;
    
    class CustomSchemaType extends BaseSchemaType
    {
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'custom_option' => 'default_value',
            ]);
        }
    }
    
  3. Nested Forms Handle nested objects/arrays by leveraging the bundle’s automatic SchemaType generation for type: "object" and type: "array":

    {
      "properties": {
        "tags": {
          "type": "array",
          "items": { "type": "string" }
        }
      }
    }
    

    Renders as a CollectionType with entry_type set to TextType.

  4. Validation Integration Combine with Symfony’s validation by adding the Schema constraint to the root form:

    $form = $this->createForm(SchemaType::class, $data, [
        'data_schema' => $schema,
        'constraints' => [
            new Schema($schema),
            new Assert\NotBlank(),
        ],
    ]);
    

Integration Tips

  • Twig Integration Pass the form to Twig and render it like any other Symfony form:

    {{ form_start(form) }}
        {{ form_widget(form) }}
        <div class="help-text">{{ form_help(form) }}</div>
    {{ form_end(form) }}
    
  • API-Driven Schemas Fetch schemas from an external API (e.g., Swagger/OpenAPI) and cache them:

    $schema = json_decode($this->httpClient->request('GET', '/api/schema')->getContent());
    
  • Dynamic Schema Updates Use Symfony’s EventDispatcher to reload schemas when they change (e.g., after a file watcher event):

    $dispatcher->addListener('schema.updated', function () {
        $this->container->get('schema_loader')->clearCache();
    });
    

Gotchas and Tips

Pitfalls

  1. Schema Parsing Errors

    • Issue: Invalid JSON schemas (e.g., missing $schema or unsupported draft versions) throw exceptions during form creation.
    • Fix: Validate schemas before passing them to SchemaType:
      use Justinrainbow\JsonSchema\Validator;
      $validator = new Validator();
      $validator->validate($schema, $schema); // Validate against itself
      if (!$validator->isValid()) {
          throw new \RuntimeException('Invalid schema');
      }
      
  2. Circular References

    • Issue: Schemas with circular $ref references (e.g., items referencing the parent schema) cause infinite recursion.
    • Fix: Use $id and $ref sparingly or resolve references manually before passing to the bundle.
  3. Form Type Overrides

    • Issue: Custom form types for specific schemas may conflict with the bundle’s defaults.
    • Fix: Extend SchemaType and override the buildForm method to inject custom types:
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $builder->add('custom_field', CustomType::class);
          parent::buildForm($builder, $options);
      }
      
  4. Validation Message Localization

    • Issue: Default validation messages (e.g., from justinrainbow/json-schema) are not translated.
    • Fix: Override messages in your validation constraints or use Symfony’s translation system:
      # config/validation.yaml
      Cyve\JsonSchemaFormBundle\Validator\Constraint\Schema:
          message: "The input '{{ propertyPath }}' is invalid."
      

Debugging Tips

  1. Inspect Generated Forms Dump the form structure to debug mapping issues:

    $form->getConfig()->getFormType()->getName();
    $form->getConfig()->getFormType()->getParent()->getName();
    
  2. Schema Validation Logs Enable verbose logging for justinrainbow/json-schema:

    $validator = new Validator();
    $validator->setLogger(new \Monolog\Logger('schema'));
    
  3. Form Options Overrides Use form_theme to customize rendering without modifying the schema:

    {# templates/form_theme.html.twig #}
    {% block schema_string_widget %}
        {{ parent() }} <span class="schema-hint">{{ form.vars.data_schema.description }}</span>
    {% endblock %}
    

Extension Points

  1. Custom Form Types Register new mappings in the bundle’s configuration (config/packages/cyve_json_schema_form.yaml):

    cyve_json_schema_form:
        form_types:
            custom_type: App\Form\Type\CustomType
    
  2. Schema Preprocessing Use a compiler pass to modify schemas before form generation:

    // src/DependencyInjection/Compiler/SchemaCompilerPass.php
    public function process(ContainerBuilder $container)
    {
        $definition = $container->findDefinition('cyve_json_schema_form.schema_processor');
        $definition->addMethodCall('addProcessor', [new Reference('app.schema_processor')]);
    }
    
  3. Validation Extensions Extend the Schema constraint to add custom validation rules:

    use Cyve\JsonSchemaFormBundle\Validator\Constraint\Schema as BaseSchema;
    
    class ExtendedSchema extends BaseSchema
    {
        public function validatedBy()
        {
            return [get_class(), 'validateCustomRule'];
        }
    
        public static function validateCustomRule($value, Constraint $constraint)
        {
            if ($value === 'forbidden') {
                throw new ConstraintViolation(
                    'Custom rule violated',
                    [],
                    [],
                    $constraint,
                    'custom_rule'
                );
            }
        }
    }
    
  4. Performance Optimization

    • Cache parsed schemas and forms:
      $cache = new \Symfony\Component\Cache\SimpleFileCache();
      $schema = $cache->get('schema_' . md5($schemaPath), function () use ($schemaPath) {
          return json_decode(file_get_contents($schemaPath));
      });
      
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
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