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

firano/form-bundle

A Laravel form bundle for defining, rendering, and handling forms with reusable field types, validation integration, and a clean API. It helps keep form logic organized and consistent across your application, from simple contact forms to complex multi-field layouts.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: this is a Symfony bundle, not a Laravel package. There is no service provider to register, no config/form-bundle.php to publish, and no Blade views. The *-bundle suffix and NeutronFormBundle description confirm it targets Symfony's Form component and DI container. If you're in a Laravel codebase, treat this repository as reference material — read it to understand the "no-JS RIA form" pattern, then reimplement the behavior with Livewire, Filament Forms, or a Blade component + small Alpine snippet. Do not try to composer require this into a Laravel app.

If you are in Symfony (the only context where it works as intended):

composer require firano/form-bundle
// config/bundles.php
return [
    Firano\FormBundle\FiranoFormBundle::class => ['all' => true],
];
bin/console assets:install --symlink public

Look here first — in this order:

  1. composer.json — check PHP and symfony/* constraints. If it pins framework-bundle to 3.x/4.x, stop. Nothing downstream matters.
  2. Form/Type/ — the real catalog of widgets. The README is almost certainly stale; the type classes are ground truth.
  3. Resources/views/Form/ — the Twig form theme. If a widget renders as a plain <input>, the answer is here.
  4. Resources/public/ — which JS libraries are bundled (jQuery, Select2, a datepicker). "No JavaScript to write" always means "JavaScript someone else wrote."

First use case: swap a plain EntityType/TextType for a richer widget without touching the entity, constraints, or data transformers:

$builder
    ->add('customer', CustomerSelectType::class, [
        'route' => 'app_customer_search',
        'minimum_input_length' => 2,
    ]);

Register the theme once, globally:

# config/packages/twig.yaml
twig:
    form_themes:
        - '@FiranoForm/Form/fields.html.twig'

Day-one loop: swap the type → configure options → let the theme emit data-* attributes → bundled JS boots the widget.

Implementation Patterns

Type-swap, not controller-swap. These are presentation-only types. Keep your property type, constraints, and data transformers exactly as they were. A rich select still submits a scalar or entity — the widget should never leak into your domain layer. If it does, that's your cue to abandon the package.

Back autocomplete with a thin JSON endpoint.

#[Route('/customers/search', name: 'app_customer_search')]
public function search(Request $request): JsonResponse
{
    $q = (string) $request->query->get('q', '');
    $rows = $this->customers->search($q, limit: 20);

    return $this->json([
        'results' => array_map(fn (Customer $c) => [
            'id' => $c->getId(),
            'text' => $c->getDisplayName(),
        ], $rows),
    ]);
}

Keep the payload shape locked to what the widget expects (usually { results: [{id, text}] }). This endpoint is now an unauthenticated-surface concern — rate-limit it and scope the search query.

Global theme + targeted overrides. Register globally, override specific {% block %}s in your own theme file only where you need project-specific markup. This keeps custom CSS/classes in one place rather than spread across every form type call.

If you're porting the pattern to Laravel (the sane path):

  • Livewire — closest conceptual match. wire:model.live on a <select> gives you the "RIA without hand-written JS" feel with first-party tooling.
  • Filament Forms — if the need is admin/RIA form scaffolding with validation and layout baked in.
  • Blade + Alpine — for the "no build step" case; still JS, but ~20 lines per widget, and you own it.

Port the behavioral spec, not the code. Extract: which field types exist, what options they accept, what conditional-visibility rules apply, how validation errors are surfaced. Reimplement in the target stack. This preserves intent while dropping an unmaintained dependency.

Gotchas and Tips

Framework mismatch is the headline gotcha. Symfony bundles rely on the HTTP kernel, DI compiler passes, and symfony/form. None exist in Laravel. There is no bridge worth writing for a 0-star, 0-dependent package. If you find yourself editing composer.json to fake Symfony autoloading, stop — you're writing a fork, not an integration.

Abandonment risk is total. 0 stars, 0 dependents, score 0, and the firano namespace maps to mid-2010s Symfony bundles. Assume no upstream fixes — no PHP 8.x bumps, no Symfony 6/7 compat, no security advisories. Before any adoption, grep composer.json for version pins; a stale framework-bundle constraint here means the package is a non-starter even in Symfony.

Security surface sits on the input boundary. Form packages handle untrusted input, CSRF, and mass assignment. With zero dependents, zero external eyes. Treat any extracted code as newly authored: rewrite, don't copy — deprecated patterns (each(), non-nullable hints, old Twig syntax) are likely present and will fail on PHP 8.2+.

"No JavaScript" is marketing. The bundle ships JS (or expects a CDN). Check Resources/public/. In a CSP-strict environment this is exactly the code you were trying to avoid — you've just moved it into the vendor tree where you can't audit it under your CSP nonce policy without forking.

The AJAX round-trip per interaction is a scaling unknown. No benchmarks exist. If the widget fires on keystroke, cache the search endpoint at the proxy/CDN layer or add debouncing in your own JS — the package may not debounce by default.

Asset publishing is required and easy to miss. assets:install (or symlink) is not run by default when public/ is gitignored in some setups; symptom is unstyled widgets with no console errors. First debug step for "widget doesn't work" is always ls public/bundles/firanoform/.

Debugging checklist when a widget falls back to a plain input:

  1. Is the form theme registered and is your type in its block list? (Resources/views/Form/)
  2. Did you pass the required options? Most types validate options in configureOptions — a missing route often silently degrades.
  3. Is data-* present in the rendered HTML? View-source, don't trust the inspector.
  4. Is the JS bundle loaded and did the widget's init run after DOM-ready? Bundled JS often hooks DOMContentLoaded — dynamically added fields (collection allow_add) will not initialize. Wire them manually after collection:entry-added.

Extension points worth knowing: the form theme block is your primary override point. The config tree (DependencyInjection/Configuration.php) tells you which widgets can be disabled globally — use it to shrink the compiled asset surface if you're only using one or two types.

Bottom line for a Laravel team: don't adopt. Use Livewire or Filament; if you need the "no-JS RIA" pattern for a spike, read this repo for 30 minutes, then build the behavior yourself. The maintenance cost of a fork-and-own is unbounded; the capability is a solved problem in the Laravel ecosystem.

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.
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
nodisrupt/laravel-agent
sierratecnologia/media-manager