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

Forms Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require avris/forms
    

    Publish the config (if available) and register the service provider in config/app.php:

    'providers' => [
        Avris\Forms\FormsServiceProvider::class,
    ],
    
  2. 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',
            ];
        }
    }
    
  3. Render the Form in Blade

    {!! Form::open('contact', 'ContactForm') !!}
        {!! Form::fields() !!}
        {!! Form::submit('Send') !!}
    {!! Form::close() !!}
    
  4. 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');
    }
    
  5. Define Routes

    Route::post('/contact', [ContactController::class, 'store'])
         ->name('contact.store');
    

Where to Look First

  • Documentation: Check vendor/avris/forms/docs or GitLab repo for field types, validation rules, and customization.
  • Examples: Look at tests/ in the package for usage patterns.
  • Config: If published, review config/forms.php for default settings (e.g., storage, validation).

First Use Case: Simple Contact Form

  1. Create ContactForm (as above).
  2. Use Form::open() in Blade with the form class name.
  3. Submit to a controller method accepting the form class as a parameter.
  4. Extend with store() or custom logic.

Implementation Patterns

Core Workflows

1. Form Definition

  • Fields: Define in $fields array with type, label, and metadata (e.g., required, placeholder).
    protected $fields = [
        'username' => [
            'type' => 'text',
            'label' => 'Username',
            'required' => true,
            'attributes' => ['class' => 'form-control'],
        ],
    ];
    
  • Validation: Override rules() to return Laravel validation rules.
    public function rules()
    {
        return [
            'username' => 'required|unique:users|min:4',
        ];
    }
    

2. Rendering

  • Blade Integration:
    {!! Form::open('profile', 'UserProfileForm') !!}
        {!! Form::field('username') !!} <!-- Renders input for 'username' -->
        {!! Form::submit('Update') !!}
    {!! Form::close() !!}
    
  • Dynamic Fields: Use Form::field('dynamic_field', ['type' => 'hidden']) for runtime fields.

3. Submission Handling

  • Controller Injection:
    public function update(UserProfileForm $form)
    {
        $form->validate();
        $form->store(); // Saves to associated model
        return back()->with('success', 'Updated!');
    }
    
  • Custom Storage: Override store() to handle non-Eloquent logic:
    public function store()
    {
        $data = $this->validated();
        // Custom logic (e.g., API call, file storage)
        return $this->successful();
    }
    

4. Conditional Logic

  • Field Visibility: Use visible() in $fields:
    'password' => [
        'type' => 'password',
        'visible' => function () {
            return request()->route('action') === 'create';
        },
    ],
    
  • Dynamic Rules: Modify rules() based on context:
    public function rules()
    {
        $rules = ['email' => 'required|email'];
        if ($this->isUpdate()) {
            $rules['email'] = 'sometimes|email';
        }
        return $rules;
    }
    

Integration Tips

Laravel Ecosystem

  • Validation: Extend with custom rules:
    use Illuminate\Validation\Rule;
    
    public function rules()
    {
        return [
            'username' => [
                'required',
                Rule::unique('users')->ignore($this->model),
            ],
        ];
    }
    
  • Events: Listen to FormSubmitted:
    event(new FormSubmitted($form));
    
  • Middleware: Protect forms with auth or throttle:
    Route::post('/form', [FormController::class, 'store'])
         ->middleware(['auth', 'throttle:10']);
    

Frontend Frameworks

  • Livewire: Bind form to a Livewire component:
    public $formData;
    
    public function mount()
    {
        $this->formData = (new UserProfileForm())->fields();
    }
    
    public function submit()
    {
        $form = new UserProfileForm($this->formData);
        $form->validate()->store();
    }
    
  • Inertia.js: Pass form data to Vue/React:
    return Inertia::render('FormPage', [
        'form' => (new ContactForm())->fields(),
    ]);
    

Testing

  • Unit Tests: Mock form validation/storage:
    $form = new ContactForm();
    $form->shouldReceive('validate')->once();
    $form->shouldReceive('store')->once();
    $form->submit();
    
  • Feature Tests: Test Blade rendering:
    $response = $this->get('/contact');
    $response->assertSee('Your Name');
    

Gotchas and Tips

Pitfalls

  1. Field Naming Conflicts

    • Issue: Overlapping field names between forms or models.
    • Fix: Use unique prefixes (e.g., user_profile_username) or namespace fields in $fields.
  2. Validation Timing

    • Issue: validate() runs on every request, even for GET.
    • Fix: Override authorize() to gate validation:
      public function authorize()
      {
          return request()->is('POST');
      }
      
  3. Model Binding

    • Issue: store() assumes an associated Eloquent model.
    • Fix: Explicitly set the model in the constructor:
      public function __construct($model = null)
      {
          $this->model = $model ?: new User();
      }
      
  4. CSRF Token Mismatch

    • Issue: Form submissions fail with "CSRF token mismatch."
    • Fix: Ensure Form::open() includes the route and that Laravel’s CSRF middleware is active.
  5. Nested Forms

    • Issue: Complex nested forms (e.g., multi-step) break rendering.
    • Fix: Use Form::group() or split into multiple form classes.

Debugging Tips

  • Validation Errors: Check $form->errors() or Laravel’s default error bag.
  • Field Rendering: Inspect the $fields array for typos or missing metadata.
  • Storage Issues: Verify the model is bound before store():
    dd($this->model); // Debug model binding
    
  • Events: Log FormSubmitted events to track submissions:
    Form::submitted(function ($form) {
        \Log::info('Form submitted', ['data' => $form->all()]);
    });
    

Configuration Quirks

  1. Default Storage

    • The package defaults to Eloquent. To use a custom storage layer:
      public function store()
      {
          $data = $this->validated();
          // Custom logic (e.g., API call)
          return $this->successful();
      }
      
  2. Field Types

    • Supported types: text, email, password, textarea, select, checkbox, radio, file.
    • Custom Types: Extend Avris\Forms\Field or use raw HTML:
      'custom_field' => [
          'type' => 'custom',
          'content' => '<input type="date" name="custom_field">',
      ],
      
  3. Conditional Logic

    • Use closures for dynamic visibility/rules:
      'terms' => [
          'type' => 'checkbox',
          'visible' => function () {
              return config
      
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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums