opifer/form-bundle
Opifer FormBundle is a PHP form-building package that provides reusable components for defining, rendering, and handling forms. It reduces boilerplate and offers straightforward integration for Symfony-style applications, making form management cleaner and more maintainable.
This bundle is archived (last release November 2015, zero stars) and targets Symfony 2.x. Treat it as a reference implementation to mine for ideas rather than a dependency you install into a new project.
Minimal steps if you are working in a legacy Symfony 2.8 app:
Install with Composer, pinning to the last tag:
composer require opifer/form-bundle:^1.0
If the tag is unavailable, fall back to dev-master and commit the resulting composer.lock.
Register the bundle in app/AppKernel.php:
new Opifer\Bundle\FormBundle\OpiferFormBundle(),
Import routing if the bundle ships controllers (submission handling, admin CRUD):
# app/config/routing.yml
opifer_form:
resource: "@OpiferFormBundle/Resources/config/routing.yml"
prefix: /forms
Update the schema so the form and field tables exist:
php app/console doctrine:schema:update --force
If you use migrations, generate a diff first and inspect the FKs between form and field tables.
Where to look first, in this order:
Entity/ — the Form and FormField (or equivalent) models and their column names. This is your real API.Form/Type/ — the dynamic form type that converts stored field definitions into Symfony form children.Resources/config/services.yml — the manager/registry services you can inject or override.Resources/views/ — Twig templates to override in app/Resources/OpiferFormBundle/views/.First use case: create a Form row plus a handful of FormField rows (text, email, textarea), then in a controller fetch the form entity, hand it to the bundle's dynamic form type, render it, and handle the request. That single loop — DB definition → Symfony form → render → handle → persist values — is the whole value proposition of the package.
Building the form from persisted definitions. The central pattern is a manager/service that walks the field collection and calls $builder->add($field->getName(), $field->getType(), $field->getOptions()) for each. Inject that service rather than reconstructing the loop in every controller:
$formEntity = $formManager->getRepository()->find($id);
$form = $this->createForm(new DynamicFormType($formManager), $formEntity);
Storing field options as JSON/serialized arrays. Labels, required, choices, placeholder, and constraint config almost certainly live in one options column. Normalize on write (always arrays, never objects) so unserialization stays predictable across Symfony versions.
Handling submissions separately from the definition. Build the Symfony form, call handleRequest, then iterate $form->getData() or the child values and persist them into a submission/value entity keyed by field. Keeping submissions in their own table lets you evolve a form definition without corrupting historical answers.
Rendering. Pass the built form view to Twig and loop the field entity collection alongside it, or just form_widget(form) if the bundle's theme is sufficient. Override templates rather than editing vendor files — the bundle is archived and you will never get upstream fixes.
Extending field types. Add your own mapping from the stored type string to a Symfony form type. A small registry (array or tagged services) is cleaner than a switch:
services:
app.form.field_type.phone:
class: AppBundle\Form\Type\PhoneType
tags:
- { name: opifer.form.field_type, alias: phone }
Post-submit hooks. Email notifications, redirects, and CRM pushes are not the bundle's job. Wire a FormEvents::POST_SUBMIT listener or an event subscriber on your submission flow instead of patching the bundle.
CMS integration. If you are also running OpiferCmsBundle, forms are typically authored through the CMS UI and this bundle is the rendering/handling half. Without the CMS, you own CRUD for the Form and FormField entities yourself.
symfony/symfony: ~2.x, PHP 5.5-era code) will block resolution. If you must run modern Symfony, port the dynamic-form-building loop into a standalone form type — it is a few hundred lines and you will save yourself a fork.getName() vs getBlockPrefix(). On Symfony 2.7/2.8 the old getName() is deprecated and logs noise. If you fork, rename; if you don't, expect deprecation spam in dev.framework.orm.mapping enables annotations, or the Form entity will silently lack metadata.type value of choice or entity may need options (class, choice list) that were valid in 2015 but not in your app. Always wrap the type lookup with a fallback to TextType and log a warning rather than throwing at render time.unserialize() an options blob that a non-admin can influence. Prefer JSON with json_decode($raw, true).services.yml. Override via app/config/config.yml service definition replacement or a compiler pass — do not edit the vendor directory.dump($form->createView()->children) at the top level is faster than guessing why a field renders blank.How can I help you explore Laravel packages today?