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

Laravel Form Builder Laravel Package

kris/laravel-form-builder

Form builder for Laravel 5 inspired by Symfony's form builder. It creates forms that are easy to modify and reuse, supports Bootstrap 3 by default, and integrates seamlessly with Laravel's FormBuilder for quick, customizable form creation. Ideal for reusable, maintainable forms and fast development.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire up (Laravel 5-style, still the documented path):

composer require kris/laravel-form-builder

Then in config/app.php:

'providers' => [ Kris\LaravelFormBuilder\FormBuilderServiceProvider::class ],
'aliases'   => [ 'FormBuilder' => Kris\LaravelFormBuilder\Facades\FormBuilder::class ],

The package pulls in laravelcollective/html and auto-binds the Form/Html aliases if they aren't already in the container — so on modern Laravel versions, check what it drags in before you commit (see Gotchas).

Where to look first, in order:

  1. The docs site (kristijanhusak.github.io/laravel-form-builder) — the README is a quickstart, not a reference.
  2. src/Field.php — the Field::TEXT, Field::TEXTAREA, Field::CHOICE, Field::CHECKBOX constants are your type vocabulary; the README examples use them, older blog posts use raw strings.
  3. resources/views/ inside the package — this is where the Bootstrap 3 markup lives. Read it before you fight it.
  4. CHANGELOG.md — this library changes binding semantics between minor versions more than you'd expect.

First use case — a CRUD form in one artisan command:

php artisan make:form Forms/SongForm --fields="name:text, lyrics:textarea, publish:checkbox"

This writes app/Forms/SongForm.php with a buildForm() method you edit:

public function buildForm()
{
    $this
        ->add('name', Field::TEXT, ['rules' => 'required|min:5'])
        ->add('lyrics', Field::TEXTAREA, ['rules' => 'max:5000'])
        ->add('publish', Field::CHECKBOX);
}

Controller:

public function create(FormBuilder $formBuilder)
{
    $form = $formBuilder->create(SongForm::class, [
        'method' => 'POST',
        'url'    => route('song.store'),
    ]);

    return view('song.create', compact('form'));
}

Blade:

{!! form($form) !!}

That's a working, CSRF-protected, Bootstrap-styled form. If you're productive within 15 minutes of that, the package is a good fit for your codebase's era.

Implementation Patterns

Form class as the single source of truth. The real payoff isn't HTML generation — it's that fields, labels, validation rules, and defaults live in one class used by both create and edit actions. Push all field definitions into buildForm() and keep controllers thin.

Create/update with model binding. Pass the model in the options and the form renders old values automatically:

$form = $formBuilder->create(SongForm::class, [
    'method' => 'PUT',
    'url'    => route('song.update', $song),
    'model'  => $song,
]);

Then $song->update($form->getFieldValues()) on submit. getFieldValues() returns only fields the form knows about, which gives you free mass-assignment scoping — but it is not a substitute for validation.

Validation flow. Rules are per-field options, which means the form doubles as your FormRequest:

public function store(FormBuilder $formBuilder)
{
    $form = $formBuilder->create(SongForm::class);
    $form->redirectIfNotValid();          // 302 back + errors + old input

    Song::create($form->getFieldValues());
    return redirect()->route('song.index');
}

For JSON/API endpoints, use $form->isValid() and $form->getErrors() and shape the response yourself. Add 'error_messages' => [...] per field (1.7.0+) to keep custom messages next to the rule instead of in a language file.

Composite forms for shared address/SEO/meta blocks. Add a child form by class and it binds, validates, and namespaces errors for you:

$this->add('address', 'form', [
    'class' => AddressForm::class,
    'label' => false,
]);

compose() is the alternative when you want to flatten another form's fields into the parent rather than nest them (fixed in 1.6.42 for the "Field already exists" exception). Use removeChild when a subclass needs to drop an inherited field.

Custom field types. Register once in config/laravel-form-builder.php under custom_fields, or extend Kris\LaravelFormBuilder\Fields\FormField and map a key to your class. This is the correct extension point for things like a datepicker wrapper, a money input, or a WYSIWYG — don't copy-paste the same options array across 20 forms.

Template overrides. Set 'template' => 'vendor.my-template' per form, or template_prefix per form/field (1.6.31) to swap markup without forking the package views. Publish the package views and edit the partials if you're changing markup globally. If you're on Bootstrap 4, install ycs77/laravel-form-builder-bs4 rather than hand-rolling templates.

Quick and dirty forms. $formBuilder->createByArray([...]) is underrated for admin filters, settings pages, and one-off import forms — no class file needed.

Rendering fragments. $form->render('name') for a single field, $form->renderUntil('field') for AJAX step forms. Useful when a page has multiple independent forms sharing markup.

Testing. Form classes are plain PHP — instantiate through FormBuilder in a unit test, fill() with input, and assert isValid() / getFieldValues(). Much faster than feature-testing the rendered HTML.

Gotchas and Tips

  • default_value was renamed to value in 1.6. If you copy an older tutorial or upgrade a legacy app, binding silently breaks. First thing to grep for.
  • The laravelcollective/html dependency is the biggest adoption risk. It auto-registers Form/Html aliases only when absent, so it can collide with aliases you already define, and its maintenance status relative to your Laravel version determines whether this package works at all. Verify against your actual Laravel version before writing 30 form classes — this is a "fits an existing L5/L6-era app" package, not a greenfield-on-Laravel-11 choice.
  • Bootstrap 3 markup is hardcoded. The default views emit form-group/control-label/form-control. Either accept it, use the BS4 companion package, or override templates deliberately — half-overriding produces inconsistent markup.
  • Reserved field names throw. Since 1.7.10 the builder rejects names that collide with form internals. If a legitimate column is called method, url, or similar, rename the field and map it manually in the controller rather than fighting the exception.
  • Unchecked checkboxes don't submit. getFieldValues() will omit them, so update() won't reset an existing true to false. Handle booleans explicitly ($data['publish'] = $request->boolean('publish')) or set the field's value and be intentional about defaults.
  • required HTML attribute is coupled to client validation. Rules containing required add the attribute only when client-side validation is on (fixed in 1.6.50 after being applied even when disabled). If you see unexpected browser validation popups, that's the switch — not your rules.
  • Translation lookup is automatic and can surprise you. Labels are translated when a matching key exists, and nested translation keys are supported since 1.7.0. If labels render as something unexpected, you have a colliding translation key; set an explicit 'label' or scope with language_name.
  • label_show vs 'label' => false. Hiding a label with false removes it from error messages in some paths; label_show (1.7.0) hides visually while keeping it addressable. Use the former only when you truly want no label.
  • Child form bugs are version-sensitive. Model binding on existing child instances, error_messages namespacing in children, multiple-select naming in subforms, and clientValidationEnabled on children were all fixed across 1.6.30–1.7.10. Pin a version ≥ 1.7.10 and don't chase these ghosts on older pins.
  • renderUntil() throws on unknown fields (changed in 1.6.31). If fields are conditional, check existence first or wrap the call.
  • Debugging a misrendered field: dump $form->getFields() and inspect the field object's type and options before touching views. Nine times out of ten the option name is wrong (e.g. passing choices vs choice_options, or selected vs value), not the template.
  • Don't query the database inside buildForm() without caching. Select choices built from Model::pluck() run on every render, including the redirect-back-on-error render. Cache the list or pass it via options.
  • redirectIfNotValid() needs withInput() semantics. It handles this, but if you roll your own redirect()->back()->withErrors($form->getErrors()), add withInput() or users lose everything they typed.
  • Best extension points, ranked: custom field classes → template overrides → config (custom_fields) → subclassing Form. Avoid patching vendor/; this package's view layer is its most volatile surface.
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.
mydnic/volet-feature-board-filament-plugin
wmde/email-address
refinery29/test-util
dees040/laravel-api-responses
teamzac/geocoder
ideatica/config-writer
keaton-php/pipe-dream
jacksonwebservices/laravel-user-suite
maksimru/conditional-laravel-debugbar
gismatul/nova-support-chat
gismatul/laravel-support-chat
networkrailbusinesssystems/oracle-api
alphabalex/messaging-made-easy
rawphp/warp
shootkiran/merobug
narakode/fineauth
numencode/wn-syncops-plugin
ibnnajjaar/mib-global-pay
refinery29/php-cs-fixer-config
parsnick/steak