Weave 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

Extra Form Bundle Laravel Package

idci/extra-form-bundle

IDCI ExtraFormBundle extends Symfony’s Form component with additional form types and helpers, making it easier to build richer forms with less custom code. It integrates cleanly into Symfony applications and reduces boilerplate for common advanced form fields.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony2-era bundle (small install base, MIT, no dependents) whose purpose is to let a FormType describe its children at runtime instead of at compile time. Treat it as a niche tool: read the source before adopting, and budget time for Symfony-version friction.

Minimal steps:

  1. Require it and register the bundle in app/AppKernel.php:
    new IDCI\Bundle\ExtraFormBundle\IDCIExtraFormBundle(),
    
    There is almost certainly no meaningful container configuration — check DependencyInjection/ for the extension class and whether any services.yml parameters are exposed.
  2. Read, in this order: Form/Type/ (the type that actually builds dynamic children), Form/Extension/ or Form/EventListener/ (the form-event subscribers that re-add fields on submit), and Resources/doc/. For a bundle this small, the code is the documentation.
  3. First use case: a form where the field list comes from data rather than from your PHP class — e.g. a "custom fields" entity, or a CMS block whose fields are configured by an admin.

The canonical starting point is a single form type that accepts a field-definition collection via an option, something in the shape of:

$form = $this->createForm(ExtraFormType::class, $data, [
    'fields' => $fieldDefinitions, // name => ['type' => ..., 'options' => [...]]
]);

Verify the exact option name and definition format against the bundle's Form/Type directory before writing anything real — that contract is the whole API surface.

Implementation Patterns

Definition-driven forms. Store field definitions as an array or a Doctrine entity (name, type, options, position). Pass them into the form type; the bundle iterates and calls $builder->add($name, $type, $options). Keep the definition objects serializable and immutable — they become your schema, so version them if users can edit them.

Per-entity dynamic forms. The common real-world case: a Product with a JSON attributes column and an AttributeDefinition table. Use a data transformer to map the flat form array to/from the JSON column so the rest of your code sees a plain array. Do not let the dynamic form type guess the data class; set data_class => null and handle mapping yourself.

Rebuilding on submit. Dynamic forms break the moment the submitted payload differs from the built form (conditional fields, AJAX-added rows). The pattern is a PRE_SUBMIT listener that reads the raw submitted data, recomputes the definition list, and adds the corresponding fields. If the bundle already ships this listener, extend it rather than wrapping it; if it does not, this is the first thing you write.

Conditional / dependent fields. Combine with core FormEvents::POST_SET_DATA + PRE_SUBMIT to add or remove children based on sibling values, and mark removed fields with 'mapped' => false rather than deleting them blindly so validation errors do not leak from stale submissions.

Validation. Dynamic children get no annotations, so every constraint must live in the field definition's options['constraints']. Build the definitions with constraints attached, and validate the definition itself (allowed types, allowed constraint classes) at the point of storage — this is your only real guardrail.

Admin UI integration. Keep form-definition editing in a separate, conventional CollectionType form. Do not let the dynamic form edit its own schema; that recursion is where these systems become unmaintainable.

Rendering. Expect to render fields in a loop ({% for child in form %}{{ form_row(child) }}{% endfor %}) and to need form_rest ordering by your position key. Custom themes are usually necessary because Symfony's default ordering is insertion order.

Gotchas and Tips

  • Symfony version drift is the biggest risk. This targets Symfony 2.x/3.x. Expect getBlockPrefix() vs getName(), Types::TEXT vs string type names, and choices_as_values deprecations. Pin your Symfony version or budget a port. On Symfony 4.4+ you can often replace this bundle entirely with FormEvents plus CollectionType — evaluate that before committing.
  • "Extra fields" errors on submit. Symfony throws This form should not contain extra fields when the submitted keys do not match the built children. Any dynamic bundle must re-add children in PRE_SUBMIT; if you see that exception, your listener order or definition recomputation is wrong.
  • getData() returns an array, not your entity. With data_class => null you lose automatic mapping. Use a data transformer or map manually in the controller; do not assume $form->getData() gives you a populated object.
  • Unmapped fields and mapped => false. Dynamic children that do not correspond to a property must be explicitly unmapped, otherwise PropertyAccess throws Neither the property ... nor one of the methods ... exist.
  • Security of user-defined types. If end users can pick a field type, you are instantiating arbitrary form types with arbitrary options. Whitelist type names against a hardcoded map, and whitelist option keys. Never pass user input straight into the type argument.
  • Performance. Building definitions per request is fine; re-querying definition rows inside buildForm for every nested form is not. Cache the definition list (Doctrine result cache or a request-scoped service) and pass it in as an option.
  • Debugging. $builder->get('field') inside PRE_SUBMIT will fail if the field was not added in PRE_SET_DATA. Dump $form->all() at the top of each listener, and enable the form profiler panel to see what actually got built versus submitted.
  • Extension points. The most reliable way to customize this bundle is a form type extension (getExtendedType()) plus your own event subscriber registered on the form — cheaper than forking, and survives minor version bumps. Only subclass the bundle's type if the option contract is genuinely too narrow.
  • Abandonment risk. 5 stars, 0 dependents, MIT. Fork it into your src/ if you adopt it, keep the license header, and isolate it behind one of your own form types so you can swap the implementation later.
  • Where to give back. If you fix the PRE_SUBMIT rebuild or add Symfony 4/5 compatibility, upstream it — for a bundle this size, one contributor makes the difference between usable and stranded.
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.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings