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

Hidden Entity Type Bundle Laravel Package

shapecode/hidden-entity-type-bundle

A Symfony bundle that adds a hidden entity form type, letting you pass entity IDs through hidden fields and have them automatically transformed back into Doctrine entities on submit—useful for forms that reference entities without showing a visible selector.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the bundle with Composer and register it (Symfony 4/5 style; with Symfony 6+ Flex, add it to config/bundles.php):

composer require shapecode/hidden-entity-type-bundle
// config/bundles.php
return [
    // ...
    Shapecode\Bundle\HiddenEntityTypeBundle\ShapecodeHiddenEntityTypeBundle::class => ['all' => true],
];

Requirements are Symfony Forms plus Doctrine (ManagerRegistry); the bundle does nothing without an entity manager available.

First use case — passing an entity reference through a form as an <input type="hidden"> instead of a visible select. For example, "create a comment for this post" where the post is known server-side and should not be user-selectable:

use Shapecode\Bundle\HiddenEntityTypeBundle\Form\Type\HiddenEntityType;

$builder->add('post', HiddenEntityType::class, [
    'class' => Post::class,
]);

In Twig, {{ form_row(form.post) }} emits a single hidden input whose value is the entity ID, and on submit the ID is transformed back into a managed entity.

Where to look first:

  • src/Form/Type/HiddenEntityType.php — the form type and its configurable options.
  • The data transformer it wires in — this is where ID ↔ entity conversion and failure behavior live.
  • The README examples for the class and manager options.

Implementation Patterns

Prepopulate on edit/create forms. The type reads its value from the underlying data object or the data option. Set the entity before rendering:

$comment = new Comment();
$comment->setPost($post);          // underlying object
$form = $this->createForm(CommentType::class, $comment);

// or explicitly on the field
$builder->add('post', HiddenEntityType::class, [
    'class' => Post::class,
    'data'  => $post,
]);

Multiple entity managers. If your project uses several Doctrine managers, pick the right one explicitly; otherwise the default manager is used and lookups may fail:

$builder->add('tenant', HiddenEntityType::class, [
    'class'   => Tenant::class,
    'manager' => 'tenant',
]);

Validate ownership, not just existence. The type only guarantees the ID resolves to an entity. In the controller (or a form event/constraint), assert the resolved entity is allowed for the current user:

if ($form->isSubmitted() && $form->isValid()) {
    $comment = $form->getData();
    if ($comment->getPost()->getAuthor() !== $this->getUser()) {
        throw $this->createAccessDeniedException();
    }
}

Combine with constraints. Since the type has no query filtering, add NotBlank/NotNull and a custom Callback or Choice-style constraint on the field to enforce membership rules.

Inject on PRE_SUBMIT. When the field isn't rendered at all (e.g., API-driven forms), add a listener to set the raw ID before transformation:

$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($post) {
    $data = $event->getData();
    $data['post'] = $post->getId();
    $event->setData($data);
});

Keep it simple in collections. Each entry of a CollectionType can use HiddenEntityType, but watch for duplicate/blank IDs when entries are added dynamically.

Gotchas and Tips

  • Never trust the hidden value. It is a plain hidden input; users can change it. Treat it as untrusted input and authorize server-side — this is the single biggest pitfall with this pattern.
  • Exposed IDs. The value is the entity's primary key, which leaks sequential IDs and makes enumeration easy. If that matters, use UUIDs/slugs and a custom transformer (see below) rather than integer IDs.
  • TransformationFailedException on bad IDs. A deleted or non-existent ID surfaces as a form error on the field ("This value is not valid"). Check $form->get('post')->getErrors() when debugging, and make sure your error rendering covers hidden fields.
  • Empty value → null. If the underlying object has no entity and no data option, the hidden input renders empty; submitting it yields null. A non-nullable association will then fail validation before your controller runs, which can be confusing.
  • Limited option set. Beyond class and manager, most EntityType options (query_builder, choice_label, multiple, expanded) are not supported. For multi-select or filtered choices, use EntityType with a hidden style, or handle it yourself.
  • multiple is not supported. Don't try to bind an ArrayCollection through this type; you'll get a single entity or an error.
  • Bundle vs. plain type. This is a small package (28 stars). If it lags your Symfony version, you can copy HiddenEntityType and its transformer into your app and register it as a tagged form.type service — no framework magic is required.
  • Extension points. To resolve by slug/UUID rather than primary key, decorate the type or subclass it and swap the data transformer: modelToView returns the identifier, viewToModel performs the repository lookup and throws TransformationFailedException when not found.
  • CSRF is unchanged. The bundle does not add any protection; your normal form CSRF token still applies, and a stolen token plus a guessed ID is all an attacker needs if you skip the ownership check.
  • Debugging tips. dump($form->get('post')->getData()) after submit to confirm transformation; enable the profiler's Forms panel to see submitted vs. transformed data; verify the manager name matches a configured Doctrine manager; and check the entity's ID is accessible (not @internal or lazy-proxy-only) when modelToView runs.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core