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

Form Laravel Package

pitch/form

Pitch\Form is a Laravel package for defining and rendering forms from PHP, aimed at keeping form structure and markup organized in code. It is a small, low-adoption package, so review its documentation and maintenance status before using it in production.

View on GitHub
Deep Wiki
Context7

Getting Started

This package wires the Symfony Form component into a Laravel application, so you get Symfony's form types, data mappers, and constraint-based validation while staying inside Laravel's container, routing, and Blade views. Treat it as an alternative to hand-rolled request validation + Blade partials when a form has enough structure (nested collections, dynamic fields, multi-step) that a form object pays for itself.

Minimal steps:

  1. composer require ph-fritsche/symfony-form — the service provider is auto-discovered.
  2. Publish the config: php artisan vendor:publish --tag=symfony-form-config, then skim config/symfony-form.php first; it controls the form factory binding, CSRF handling, and the view/template resolution used when rendering.
  3. Look at the container binding for the form factory (FormFactoryInterface) — that's the seam everything else goes through, and the thing you'll mock in tests.
  4. First use case: a Create/Edit form for one Eloquent model. Define a FormType class, render it in a Blade view, and handle it in a controller. That end-to-end path exercises field building, data mapping, validation, and error rendering — the four things that break.

As of v1.2.0 you can skip the manual ['data' => $model] wiring in the common case: the form data (entity) can be resolved from attributes, so route-model binding flows into the form automatically. Start with the annotated-controller path if you're on PHP 8, and fall back to the explicit data option when you need to override it.

Implementation Patterns

FormType as the unit of reuse. Put buildForm() in a dedicated class per resource (App\Forms\PostType), keep controllers thin. Constraints live on the type, not in the controller — that's the whole point of moving off $request->validate().

Controller triad. A typical action is: create the form with the factory, let the package bind the request, then branch on isSubmitted() && isValid(). On success call getData() and persist; on failure pass createView() to the view. Don't reach into $request->all() — the form is the input boundary.

Attribute-driven data resolution (new in v1.2.0). Annotate the controller argument/action with the package's form-data attribute and the entity is resolved for you, typically from the route parameter, instead of you passing ['data' => $post]. Pattern this buys you:

  • Edit/update actions become one-liners for data wiring; the attribute is the single declaration of "where does this form's data come from".
  • Keep the attribute on the controller, not the FormType — the FormType should stay unaware of routing so it remains reusable in console commands and tests.
  • Explicitly passing data in the options array should still win; use that as your escape hatch for non-routable cases (e.g. a "duplicate this post" screen).

Collections and relations. Use CollectionType with entry_type for has-many relations, and EntityType-style choices for belongs-to. Pair with PRE_SUBMIT/POST_SUBMIT listeners for fields whose choices depend on another field's value — this is where the Symfony model earns its keep over manual validation.

Layering with Laravel validation. Prefer Symfony constraints for anything the form owns, and reserve Laravel FormRequest/Rule objects for request-level concerns (authorization, throttling). Running both against the same payload doubles your error surface.

Testing. Build the type through the container in a feature test and submit an array directly; assert on isValid() and getErrors(). This is faster and more precise than driving the HTML form, and it's the cheapest way to regression-test attribute resolution when you upgrade.

Gotchas and Tips

  • Two CSRF systems. Symfony's form CSRF extension and Laravel's VerifyCsrfToken middleware can both be active. Pick one, disable the other in config/middleware — the failure mode (419s or "invalid CSRF token" form errors) looks like a routing bug and isn't.
  • Double validation. If you validate with both Symfony constraints and a FormRequest, users see duplicate messages and you get two sources of truth for "is this valid". Pick a lane.
  • Attribute precedence and caching. The new attribute resolution only kicks in when no explicit data option is supplied. After adding or changing an attribute, run php artisan optimize:clear — cached/compiled container state and opcache can leave you resolving the old target, and the symptom is a mysteriously empty form rather than an exception. Attributes are not inherited from parent classes or interfaces, so annotate the concrete controller method.
  • Submitted vs. valid. isSubmitted() and isValid() are separate for a reason; calling getData() before validation gives you unvalidated, partially-mapped input. Also remember isValid() returns false rather than throwing — check it, don't assume.
  • Mapping surprises. Eloquent's $fillable/$guarded and accessor/mutator behavior interact with the data mapper. If a field silently doesn't persist, check the mapper config and the model's guard settings before suspecting the form.
  • Debugging errors. $form->getErrors(true) (deep) returns a FormErrorIterator; plain getErrors() only gives top-level errors and is why "the form is invalid but shows nothing" happens. dump($form->createView()) is the fastest way to see what the view layer is actually being handed.
  • Extension points. Custom FormTypeExtension for cross-cutting behavior (help text, CSS classes, audit fields) beats copy-pasting options into every type. A FormTypeGuesser is the right hook if you want types inferred from model metadata.
  • Version note. v1.2.0 is additive — no deprecations or breaks in the release notes — so upgrading from 1.1.0 is low risk. Smoke-test any controller where you rely on implicit route-model binding into a form, since that's the path the new feature touches.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect