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

Form Bundle Laravel Package

gregwar/form-bundle

Gregwar FormBundle is a Symfony bundle that provides reusable form types, extensions, and rendering helpers for PHP applications. It simplifies building and customizing Symfony forms while keeping integration lightweight and straightforward, ideal for projects that want concise form tooling without...

View on GitHub
Deep Wiki
Context7

Getting Started

gregwar/form-bundle gives you a single, focused form type: entity_id. Instead of an EntityType select that loads every row of a table, it works with the identifier of an entity as a plain input value, then converts that ID back into an entity on submit via a Doctrine data transformer. The sweet spot is autocomplete / AJAX-driven pickers and edit forms where the entity is already known.

Minimum setup:

composer require gregwar/form-bundle

Register the bundle (Symfony 4+ config/bundles.php):

return [
    // ...
    Gregwar\FormBundle\GregwarFormBundle::class => ['all' => true],
];

Or on Symfony 3-era kernels:

$bundles = [
    new Gregwar\FormBundle\GregwarFormBundle(),
];

First use case — an edit form where a related entity is picked via a JS autocomplete widget:

use Gregwar\FormBundle\Form\Type\EntityIdType;

$builder
    ->add('category', EntityIdType::class, [
        'class' => Category::class,
    ]);

The field renders as a text input; you attach your autocomplete JS, and on submit the bundle's transformer resolves the submitted ID to a Category. If you are unsure of option names for your installed version, look first at src/Form/Type/EntityIdType.php (options in configureOptions) and the transformer in src/Form/DataTransformer/. That is the fastest way to learn the exact API — the bundle is small enough to read in a few minutes.

Implementation Patterns

1. Autocomplete picker (the primary use case). Keep the entity_id field, attach Select2 / jQuery UI autocomplete to the rendered input, and expose an endpoint returning [{id, text}]:

{{ form_row(form.category) }}
$('#post_category').select2({
  ajax: {
    url: '/api/categories',
    dataType: 'json',
    processResults: data => ({results: data})
  },
  minimumInputLength: 2
});

On submit, only the ID travels across the wire; no full choice list is loaded server-side.

2. Reuse the transformer on a normal TextType. If you don't want the bundled type, wire the transformer yourself:

use Gregwar\FormBundle\Form\DataTransformer\EntityToIdTransformer;
use Symfony\Component\Form\Extension\Core\Type\TextType;

$builder->add('category', TextType::class, ['required' => false]);
$builder->get('category')->addModelTransformer(
    new EntityToIdTransformer($em, Category::class)
);

This is a good extension point when you need custom HTML data-* attributes or a different widget.

3. Edit forms where the value is already set. Because the type maps entity ⇄ ID, form.vars.value is the raw ID and the input is pre-filled automatically. If you only want to display it, render the ID directly and use disabled/readonly:

->add('category', EntityIdType::class, [
    'class'    => Category::class,
    'disabled' => true,
])

4. Controller flow is ordinary Symfony. The transformer hides the ID/entity conversion, so persist/flush logic is unchanged:

$form = $this->createForm(PostType::class, $post);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
    $em->flush();
    return $this->redirectToRoute('post_show', ['id' => $post->getId()]);
}

$form->getData() yields a real Post with category set to a Category (or a Doctrine proxy). This makes the type a drop-in replacement for EntityType in most CRUD forms.

5. Testing. Because the type is thin, test it by submitting the form with an ID string and asserting the resulting entity, plus a mock/real EM for the transformer. You rarely need a full kernel test.

6. Where it beats EntityType. Use entity_id whenever the choice list is large, dynamic, or AJAX-fed. Use standard EntityType with a choice_loader when you actually need a server-rendered <select>.

Gotchas and Tips

  • Empty / null input. Submitting an empty string should map to null. Mark the field 'required' => false and confirm your EntityToIdTransformer version handles '' (some releases only short-circuit on null). Test an empty POST early — this is the most common surprise.
  • Invalid IDs fail silently. If the transformer can't find the ID, it typically resolves to null rather than throwing. Pair the field with a NotBlank constraint plus a custom validator (or check form->getErrors()) so tampered/typo'd IDs surface as a validation error, not a silent unlink.
  • Security. A hidden or text-submitted ID is fully client-controlled. Always authorize after resolution — a valid ID for an entity the user doesn't own is still an attack. The transformer only proves existence.
  • Bundle registration and autoconfiguration. This is an older bundle (getName()-era APIs). On Symfony 5+ the form type may not be auto-tagged; if you get "type not found", define the service manually and tag it with form.type, or instantiate it yourself. Verify the installed version against your Symfony release before committing.
  • Proxies, not hydration. getData() may return a lazy Doctrine proxy. That's fine for persisting, but calling getters triggers queries; avoid iterating it in a loop over many rows.
  • Don't dump() the whole entity. When debugging a submitted form, dump the ID via $form->get('category')->getData()->getId() instead of the object graph — it keeps the request fast and readable.
  • Extension points. Subclass EntityIdType to add JS attributes (attr: ['data-autocomplete-url' => ...]) or to default options like class and em; swap in your own data transformer for cache-backed ID lookups or composite keys.
  • by_reference and mapped. For single-valued associations, defaults are fine; if you set mapped => false, the transformer still runs for display but the entity won't be persisted — a useful trick for read-only "current value" fields.
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.
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
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core