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

X Form Laravel Package

vmphobos/x-form

x-form is a Laravel/PHP package for defining and rendering forms with a clean, reusable API. It helps organize fields, handle validation and form state, and keep form logic maintainable across Blade views and application code.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and pin.

composer require vmphobos/x-form:2.1.0

Pin the exact version, not ^2.0. The v2.1.0 release notes contain no changelog or migration guidance, so floating constraints mean you absorb undocumented changes on the next composer update.

Look here first, in this order:

  1. README.md — the only authoritative usage source.
  2. src/ — the service provider (component registration), any Form/Field classes, and the validation bridge. This tells you whether the abstraction is thin (good) or owns your data model (bad).
  3. resources/views/ — the Blade components. Read these before styling anything; you will almost certainly publish and override them.
  4. tests/ — the most reliable documentation for a package with a thin README.
php artisan vendor:publish --provider="Vmphobos\XForm\XFormServiceProvider"

Inspect what tags appear; publish config and views separately if the package supports it.

First use case — a create form. The package is described as "one line" Blade components, so the smallest useful increment is a three-field form rendered from a fluent definition. The exact method names below are illustrative — confirm them against src/ before committing to a shape:

// app/Livewire/ContactForm.php or a controller
use Vmphobos\XForm\Form;

$form = Form::make()
    ->post(route('contact.store'))
    ->fields(fn ($f) => $f
        ->text('name')->label('Name')->rules('required|max:255')
        ->email('email')->label('Email')->rules('required|email')
        ->textarea('message')->label('Message')->rules('required')
    );
<x-form :form="$form" />

Do this once in a scratch route before wiring it into a real feature. You want to see the generated HTML, the name attributes, and whether validation errors and old() input repopulate — that last part is the usual failure point in form packages.


Implementation Patterns

Centralize definitions, don't inline them. Put form definitions in app/Forms/*.php (or static methods on the form's backing model) and return them from a single method. Both the controller and the Blade view consume the same object, so a field rename is one edit, not a hunt through templates.

final class PostForm
{
    public static function make(?Post $post = null): Form
    {
        return Form::make()
            ->model($post)
            ->action($post ? route('posts.update', $post) : route('posts.store'))
            ->method($post ? 'PUT' : 'POST')
            ->fields(fn ($f) => $f
                ->text('title')->rules('required|max:255')
                ->select('status')->options(PostStatus::cases())->rules('required')
                ->textarea('body')->rules('required')
            );
    }
}

Create/edit share one definition via model binding. Pass null for create and the model for edit. Verify the package handles casting (enums, datetime, JSON columns) — if it doesn't, normalize in the model's accessors rather than special-casing the view.

Keep validation ownership in one place. The package advertises "Laravel-native validation integration." Pick one of two modes and stick to it:

  • Package owns rules — the fluent ->rules() calls feed $request->validate() in the controller. Do not also declare a FormRequest with the same rules; drift is guaranteed.
  • FormRequest owns rules — the fluent definition supplies labels and rendering only.

The first is more idiomatic for this package, but it couples your validation source of truth to a 0-star dependency. If the rules are business-critical, keep a FormRequest as the authority and treat the fluent rules as display hints.

Livewire: bind to public properties, not the form object. If the package targets Livewire, the natural pattern is one public property per field plus a rules() method on the component:

class ContactForm extends Component
{
    public string $name = '';
    public string $email = '';
    public string $message = '';

    protected function rules(): array
    {
        return ['name' => 'required|max:255', 'email' => 'required|email', 'message' => 'required'];
    }

    public function submit(): void
    {
        $this->validate();
        // persist
        $this->reset();
    }
}

Render the package's field components inside the Livewire view with wire:model. Confirm the components forward wire:model — if they strip unknown attributes, you'll need the published views.

Extend field types, don't fork. Register custom field components in the published config or service provider and keep them in app/View/Components/Form/. A custom field that composes the package's base component survives upgrades; a forked one does not.

Testing. Feature-test the POST path independently of the component (that's framework behavior), and use assertSee on labels and assertSee('name="title"', false) on rendered output to catch silent markup regressions after upgrades.


Gotchas and Tips

  • The release notes are empty. v2.1.0 is a minor bump with no changelog. Before any upgrade, run git diff v2.0.0..v2.1.0 in the vendor checkout or on GitHub. Absence of a breaking-change notice is not evidence there isn't one.
  • Zero stars means you are the QA team. There is no visible security disclosure route. For anything touching auth or personal data, treat this as unpriced risk and consider whether the saved boilerplate is worth it.
  • Verify old() and error repopulation immediately. A form package that renders fields but doesn't restore input after a failed validation redirect is unusable in practice. Test: submit invalid data, confirm the redirect back shows previous values and per-field error text.
  • Check CSRF and method spoofing. @csrf and @method('PUT') must be emitted by the component or documented as your responsibility. A missing @csrf produces a 419 that looks like an auth bug.
  • CSS assumptions. "Sensible defaults" usually means an opinionated Tailwind class set. Publish the views and override rather than appending classes in every call site.
  • Dynamic field sets need wire:key. If you loop field components (repeatable rows, line items), add a stable wire:key per iteration or Livewire will reuse DOM nodes and mangle values.
  • Nested data and array notation. Confirm how the package names inputs for nested fields (items[0][name] vs items.0.name). Get this wrong and validation passes while the database gets nothing.
  • Debugging rendering issues: php artisan view:clear, then inspect the raw HTML in the browser. If you've published views, ddd($form) at the top of the published Blade file to see the form object's shape.
  • Design for the exit ramp. Keep field definitions expressible as plain arrays and rules expressible as FormRequest syntax. The realistic scenario for a 0-star package is that you replace it in 18 months; the cost of that swap should be measured in hours, not a refactor.
  • Assign an owner. Unowned dependencies in a critical path decay silently. If nobody on the team is responsible for tracking this package's releases, don't put it on a path that takes payments or stores PII.
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.
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json
refinery29/php-cs-fixer-config
hotmeteor/eco-env
mvaliolahi/hydrate
wearede/tbcpay-php
parsnick/steak
thibaud-dauce/mattermost-php
multilinguals/apollo-client
antaresbr/collection
kr0lik/phpstan-rules