anahkiasen/former
Former is a powerful, flexible form builder for Laravel that makes creating complex forms simple. It offers Bootstrap and Foundation styling, model binding, validation integration, macros, and clean, expressive syntax for fast, maintainable form markup.
Install with Composer and register the service provider:
composer require anahkiasen/former
php artisan vendor:publish --provider="Former\FormerServiceProvider"
On Laravel 5.5+ auto-discovery registers everything; on older versions add Former\FormerServiceProvider to config/app.php and alias 'Former' => Former\Facades\Former::class.
Where to look first:
config/former.php — this is the single most important file. It controls framework (default TwitterBootstrap3), default_form_class, live_validation, label sizing, and CSRF behaviour.Former\Former facade docblock — it lists every field method (text, select, checkbox, file, textarea, date, submit, button, actions, hidden, …).Former\Traits\Field — the chainable options available on every field (label, help, placeholder, class, rules, required, append, prepend).Your first real use case: a resource edit form bound to an Eloquent model.
{!! Former::horizontal_open()->route('users.update', $user)->method('PUT') !!}
{!! Former::populate($user) !!}
{!! Former::text('name')->label('Full name') !!}
{!! Former::email('email')->help('We never share this.') !!}
{!! Former::select('role')->options(['admin' => 'Admin', 'user' => 'User']) !!}
{!! Former::checkbox('active')->text('Account is active') !!}
{!! Former::actions()->large_primary_submit('Save') !!}
{!! Former::close() !!}
populate() handles both models and plain arrays, and the service provider wires Laravel's session oldInput and error bag in automatically, so re-rendering after a failed validation "just works".
Layout modes are set at the form tag, not per field. Use Former::horizontal_open(), Former::inline_open(), or Former::open() (vertical) and match it with a bare Former::close(). Mixing modes on one page produces broken markup because Bootstrap grid classes come from the form-level config.
Binding. Former::populate($model) before rendering is the idiomatic path. For multi-model or partial forms, pass an array of models or call Former::setFieldValue('name', $value) for surgical overrides. Values resolve at render time, so field order relative to populate() rarely matters — but explicit setFieldValue() always wins.
Field-type specifics. Selects need ->options([...]) plus optionally ->select($value); checkboxes use ->check($bool); radios use ->radios([...]) on a parent field so the group shares id/name/error state. Files need Former::open_for_files() (or ->accept() on the open tag) to emit enctype="multipart/form-data".
Validation display. Former::withErrors($errors) (or Former::withErrors($validator)) attaches a message bag. Former then renders .help-block error text per field and adds has-error classes. The service provider's adapter pulls session('errors') automatically, so most apps never call this directly.
->rules() is cosmetic unless you opt in. It writes HTML5 required/pattern/min attributes and generates human-readable help hints. It does not validate. Server-side rules still belong in your FormRequest or controller.
Live validation. Former::liveValidation('users.validate') (a route name or URL) emits a JS hook that the bundled Bootstrap adapter uses to POST per-field values and get JSON back. This is the one feature that needs client-side wiring in former.php and a JSON endpoint.
Macros for repeated controls. Former::macro('search', function () { return Former::text('q')->append(Former::submit('Go')); }) keeps a shared search bar in one place; macros are registered in a service provider and behave like any other field.
Custom fields. Former::extend('rating', RatingField::class) where the class extends Former\Fields\Field and implements render(). Use this to wrap third-party widgets (date pickers, tag inputs) without abandoning Former's populate/error plumbing.
Framework switching. Former::framework('Nude') swaps the renderer at runtime — invaluable in tests and when you're not on Bootstrap. The Nude framework emits near-plain HTML, which is easier to assert against and easier to style yourself.
Standalone (non-Laravel). Bootstrap a container and config repository, construct Former\Former, then set a framework. The field API is identical; only the session/old-input/error-bag integration disappears, so plan to call withErrors(), populate(), and setFieldValue() yourself.
{!! !!}, not {{ }}. The single most common beginner error produces double-escaped markup and looks like the package is broken.Former::close() is mandatory. Unbalanced opens leak an unclosed <form> into every subsequent partial on the layout.composer require and the README can quietly disagree.0, '0', and '' in selects and checkboxes. Loose comparison in older versions can make "0" a truthy/selected edge case. Write a quick test with 0 and '0' values before shipping.Former::open() instead of open_for_files() — the form submits but $request->file() is empty and nothing errors.Session::start() disabled, or behind a custom validation handler that doesn't flash, populate and errors won't appear. Former::withErrors() + manual populate() is the deterministic fallback.config:cache freezes former.php. In production, editing the framework or label width without re-caching is a classic "why did nothing change".Former::text('address[line1]') renders fine, but withErrors() needs the dotted key (address.line1). Mismatches result in a field that never turns red.Former::text('name')->render() returns the HTML string — use it in php artisan tinker or a unit test to inspect output without a browser. Former::getFramework() confirms which adapter is actually active, which catches "I changed the config but auto-discovery used another".Former\Framework\AbstractFramework and declare $fieldClasses plus wrapper methods (open, close, submit, etc.). Missing one method throws at render time, not boot time.X-CSRF-Token; your endpoint must return the expected { "result": true/false, "messages": [...] } shape or the field will silently stay neutral.How can I help you explore Laravel packages today?