avris/forms
Laravel form builder package for quickly generating, rendering, and validating forms. Provides reusable form components, field types, and helpers to streamline form handling, input processing, and UI integration in your application.
Installation
composer require avris/forms
Publish the config (if available) and register the service provider in config/app.php:
'providers' => [
Avris\Forms\FormsServiceProvider::class,
],
First Form Class
Create a form class in app/Forms (e.g., ContactForm.php):
namespace App\Forms;
use Avris\Forms\Form;
class ContactForm extends Form
{
protected $fields = [
'name' => ['type' => 'text', 'label' => 'Name', 'required' => true],
'email' => ['type' => 'email', 'label' => 'Email', 'required' => true],
];
public function rules()
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email',
];
}
}
Render the Form in Blade
{!! Form::open('contact', 'ContactForm') !!}
{!! Form::fields() !!}
{!! Form::submit('Send') !!}
{!! Form::close() !!}
Handle Submission In your controller:
public function store(ContactForm $form)
{
$form->validate();
$form->store(); // Saves to DB (Eloquent model by default)
return redirect()->route('thank-you');
}
Define Routes
Route::post('/contact', [ContactController::class, 'store'])
->name('contact.store');
vendor/avris/forms/docs or GitLab repo for field types, validation rules, and customization.tests/ in the package for usage patterns.config/forms.php for default settings (e.g., storage, validation).ContactForm (as above).Form::open() in Blade with the form class name.store() or custom logic.$fields array with type, label, and metadata (e.g., required, placeholder).
protected $fields = [
'username' => [
'type' => 'text',
'label' => 'Username',
'required' => true,
'attributes' => ['class' => 'form-control'],
],
];
rules() to return Laravel validation rules.
public function rules()
{
return [
'username' => 'required|unique:users|min:4',
];
}
{!! Form::open('profile', 'UserProfileForm') !!}
{!! Form::field('username') !!} <!-- Renders input for 'username' -->
{!! Form::submit('Update') !!}
{!! Form::close() !!}
Form::field('dynamic_field', ['type' => 'hidden']) for runtime fields.public function update(UserProfileForm $form)
{
$form->validate();
$form->store(); // Saves to associated model
return back()->with('success', 'Updated!');
}
store() to handle non-Eloquent logic:
public function store()
{
$data = $this->validated();
// Custom logic (e.g., API call, file storage)
return $this->successful();
}
visible() in $fields:
'password' => [
'type' => 'password',
'visible' => function () {
return request()->route('action') === 'create';
},
],
rules() based on context:
public function rules()
{
$rules = ['email' => 'required|email'];
if ($this->isUpdate()) {
$rules['email'] = 'sometimes|email';
}
return $rules;
}
use Illuminate\Validation\Rule;
public function rules()
{
return [
'username' => [
'required',
Rule::unique('users')->ignore($this->model),
],
];
}
FormSubmitted:
event(new FormSubmitted($form));
auth or throttle:
Route::post('/form', [FormController::class, 'store'])
->middleware(['auth', 'throttle:10']);
public $formData;
public function mount()
{
$this->formData = (new UserProfileForm())->fields();
}
public function submit()
{
$form = new UserProfileForm($this->formData);
$form->validate()->store();
}
return Inertia::render('FormPage', [
'form' => (new ContactForm())->fields(),
]);
$form = new ContactForm();
$form->shouldReceive('validate')->once();
$form->shouldReceive('store')->once();
$form->submit();
$response = $this->get('/contact');
$response->assertSee('Your Name');
Field Naming Conflicts
user_profile_username) or namespace fields in $fields.Validation Timing
validate() runs on every request, even for GET.authorize() to gate validation:
public function authorize()
{
return request()->is('POST');
}
Model Binding
store() assumes an associated Eloquent model.public function __construct($model = null)
{
$this->model = $model ?: new User();
}
CSRF Token Mismatch
Form::open() includes the route and that Laravel’s CSRF middleware is active.Nested Forms
Form::group() or split into multiple form classes.$form->errors() or Laravel’s default error bag.$fields array for typos or missing metadata.store():
dd($this->model); // Debug model binding
FormSubmitted events to track submissions:
Form::submitted(function ($form) {
\Log::info('Form submitted', ['data' => $form->all()]);
});
Default Storage
public function store()
{
$data = $this->validated();
// Custom logic (e.g., API call)
return $this->successful();
}
Field Types
text, email, password, textarea, select, checkbox, radio, file.Avris\Forms\Field or use raw HTML:
'custom_field' => [
'type' => 'custom',
'content' => '<input type="date" name="custom_field">',
],
Conditional Logic
'terms' => [
'type' => 'checkbox',
'visible' => function () {
return config
How can I help you explore Laravel packages today?