laraform/laraform-laravel
LaraForm for Laravel is the backend companion to the LaraForm form builder, handling server-side validation, model binding, file uploads, and data processing for Vue-powered forms. Build complex, dynamic Laravel forms with less boilerplate.
Install and confirm the constraints first. The package is a thin Laravel bridge for the LaraForm Vue form builder, so you install two halves:
composer require laraform/laraform-laravel
php artisan vendor:publish --provider="Laraform\Laravel\LaraformServiceProvider"
npm install laraform --save # Vue 2 only
Before writing a single form, read vendor/laraform/laraform-laravel/src/Form.php end to end. It is the actual API surface, it is small, and the published docs at laraform.io (separate from the repo) are the real manual — the GitHub README is minimal and the repo has only 14 stars, so the base class is your most reliable reference.
Register the frontend once. Add the LaraForm Vue plugin in your app.js, then render a form with the <laraform :form="form"> component, passing the serialized form object your controller hands to the view.
First use case — a create/edit form for a single Eloquent model. Generate a form class:
class UserForm extends \Laraform\Laravel\Form
{
public function elements()
{
$this->text('name')->rules('required|max:255');
$this->email('email')->rules('required|email|unique:users,email');
$this->password('password')->rules('sometimes|min:8');
}
}
Then in a controller: build the form, bind the model on edit, pass the serialized form to the view, and let the package's submit route validate and persist. The whole value proposition is that one PHP file defines the field list, the validation rules, and the persistence — the Vue side renders it and posts back to the same rules. Get one CRUD screen working end to end before touching anything else; if that path is smooth, the rest is repetition.
Treat the form class as the schema of record. The productive workflow is: elements and rules are declared in PHP only, never duplicated in Vue. The frontend reads the serialized rules to do client-side validation for free, and the same rules run server-side on submit. If you find yourself hand-writing validation in JavaScript, you've drifted off the package's model.
One form class per resource, composed by inheritance. Put shared fields on a BaseForm and have UserForm, AdminUserForm, etc. extend it and override only the deltas. This is the main lever for keeping large apps sane with this package; inheritance is cheap, copy-paste of element definitions is not.
Bind, validate, save as three separate steps. Even though the package will happily do the whole cycle in one submit handler, the day-to-day pattern that survives real requirements is:
$form->bind($model) on edit so values populate.$form->validate($request->all()) (or let the controller do it) and branch on the result.$form->save() only after you've done your domain side-effects.That middle branch is where you hook emails, events, and transactions. Treat save() as a convenience, not a controller.
Handle relations with nested element groups. For hasMany and belongsTo, use the package's object/list element types rather than flattening fields into address_line_1 style names. It's more work up front and much less work when the relation changes.
Centralize the submit endpoint. Rather than a controller per form, route all submissions through one controller that resolves the form class from the request (a form key or a route parameter) and returns a uniform JSON error envelope. The frontend component expects a specific error shape — match it once, in one place.
Test forms directly, without HTTP. Form classes are plain PHP: instantiate, pass an array payload into the validator, assert on errors and on the resulting model state. This is far faster than driving the browser and catches the majority of schema mistakes.
Check the license before commercial use. The repo reports NOASSERTION, which means GitHub could not classify it. Do not assume MIT. Read LICENSE in the vendor directory and get sign-off if you're shipping commercially.
Assume you are the maintainer. Low stars, low recent activity, Vue 2-only. Pin exact versions in composer.json and package.json, commit the lockfiles, and expect no Laravel 9/10 compatibility without patching the service provider yourself. Budget for a fork.
Client and server validation will drift. The frontend validation is a convenience; anything security-relevant must be enforced server-side with Laravel rules you control. For custom rules, prefer Validator::extend in a service provider over writing a LaraForm-specific rule object — you keep the escape hatch open.
Most "the field doesn't render" bugs are in PHP, not Vue. When something is wrong, dd(json_encode($form->toArray())) (or your serialization call) and inspect the payload. Field visibility, ordering, and conditional logic are all decided server-side; the browser is just a renderer. Debug the JSON, not the component.
Mass assignment bites on save. save() uses standard Eloquent filling, so a field not in $fillable will silently vanish after a successful validation. If a form validates but the value isn't persisted, look at the model before you look at the package.
Watch the conditional-field trap. Client-side conditions that hide fields often also stop them from being submitted. Server-side rules must then use sometimes / nullable or you'll get spurious validation failures. This is the single most common source of confusing "required field is empty" reports.
Know the extraction path. The good news is that the Laravel side is just rules on a class — if you later migrate to Livewire, Inertia, or a bespoke Vue 3 frontend, you can keep the form classes as validation schemas and swap the transport. Design your controllers so the form class is called from one place; that keeps the exit cheap.
Use custom elements sparingly. The extension point for new element types is real, but each one couples you to the frontend package's internals. Prefer composing existing types until you hit a genuine wall.
How can I help you explore Laravel packages today?