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

Parsley Bundle Laravel Package

j-ben87/parsley-bundle

Symfony bundle that integrates Parsley.js client-side form validation with Symfony forms. It maps form constraints to Parsley attributes, cuts manual markup, and helps add consistent browser-side validation with minimal configuration. Useful when you want browser-side checks that complement server-s...

View on GitHub
Deep Wiki
Context7

Getting Started

First, confirm the stack. This is a Symfony bundle (bjd-php/parsley-bundle), not a Laravel package. It reads symfony/validator constraint metadata off form types. If you are on Laravel, there is no constraint graph to introspect — Illuminate\Validation rules are not the input this package consumes. For Laravel, use the rest of this document as a porting guide for a ~300-line rule-to-attribute helper; do not attempt to install the bundle.

Symfony path — minimal setup:

composer require j-ben87/parsley-bundle
// config/bundles.php
JBen87\ParsleyBundle\ParsleyBundle::class => ['all' => true],

Ensure the Symfony Form component and Validator are already in use (they almost certainly are). Confirm the Parsley runtime is loaded on the pages that need validation — the bundle only emits data-parsley-* attributes; it does not ship Parsley or jQuery.

Where to look first in the source:

  1. The form type extension — this is where attributes get attached to fields during form build. It is the integration seam.
  2. The constraint mapping table (constraint class → Parsley rule name → attribute name). This is the single most important thing to read; it defines exactly what coverage you get and what silently no-ops.
  3. The attribute rendering/escaping path — attribute values include your constraint messages, so escaping matters.

First use case. Pick a simple form with a NotBlank + Email combo, or NotBlank + Length:

$builder
    ->add('email', EmailType::class, [
        'constraints' => [
            new NotBlank(['message' => 'Email is required']),
            new Email(['message' => 'Enter a valid email']),
        ],
    ]);

Render it normally with form_row() / form_widget(), initialize Parsley once on the form, and inspect the rendered HTML. You should see data-parsley-required, data-parsley-type="email", and matching data-parsley-required-message / data-parsley-type-message attributes. That rendered HTML is your contract — check it before wiring up anything else.

Implementation Patterns

Constraint-driven, not attribute-driven. Declare rules on the form type's constraints option — the bundle does the translation. Do not hand-write data-parsley-* attributes alongside the constraints; that reintroduces the duplication the package exists to remove, and it will drift.

Per-form rollout with a feature flag. Gate the Parsley initialization (or the extension, if you can toggle it) behind a config flag scoped to one form family first. Because the server-side constraints are untouched, rollback is just "stop initializing Parsley" — nothing authoritative lives in the attributes.

Map your coverage table before you ship. For each form you touch, enumerate the constraints in use and classify each one:

  • Maps cleanly — NotBlank, Length, Email, Regex, Range, Choice (per description).
  • Maps approximately — e.g. Length min/max mapped to Parsley min/max may not match your message semantics; Regex flags/anchoring may differ between PHP PCRE and JS regex.
  • Server-only — Callback, When, Valid traversal, group-conditional constraints, uniqueness. These must not appear to be validated client-side.

Keep this table in the repo. It is the artifact that prevents silent divergence later.

Custom messages. Pass a message on each constraint; it flows through as data-parsley-<rule>-message. If the app uses the Symfony translator, verify whether the bundle runs the message through it (unverified) — if not, either translate at declaration time or in a post-render step.

Multi-step wizard pattern. Initialize Parsley per step's <form> element, not on the whole document, and re-bind after each step renders (AJAX-loaded steps need re-init). Use Parsley's data-parsley-group namespacing if the server constraints are logically grouped, so a step validates only its slice.

Test the mapping, not just the form. Add a table-driven test asserting the emitted attribute set for each constraint you rely on. This is cheap and catches upstream or Symfony-version regressions — the failure mode you care about is an attribute quietly disappearing. A rendered-HTML assertion per constraint type is the right shape.

Instrumentation pairing. Since the package emits no telemetry, wire your own: count client-blocked submits and server-side validation failures per session. That's the data that tells you whether the UX win materializes — without it, "we added client validation" is anecdotal.

Laravel port shape (if that's your path). Implement ParsleyAttributes::fromRules(array $rules): array reading Illuminate\Validation rule strings (required, max:255, email, regex:/.../) and emitting the same data-parsley-* shape. Expose it as a Blade component or a @parsley-style directive that merges into the field's attribute bag. Reuse the bundle's mapping semantics and escaping approach as reference, rewrite the plumbing.

Gotchas and Tips

Silent no-ops are the primary failure mode. A constraint without a Parsley equivalent emits nothing — the browser sees no rule and does not block. That is fail-safe (server still rejects) but invisible. Make unsupported constraints loud in dev (log a warning when a constraint doesn't map) and degrade quietly in prod. This is the single highest-value hardening you can add to a fork or port.

Never relax the server-side constraints. The attributes are a UX affordance. Keep every validator constraint authoritative, and correct any stakeholder who reads "client-side validation" as a control.

Attribute injection risk. Messages and option values land inside HTML attributes. Assume the escaping path is unproven absent a review — test with messages containing ", <, >, and &, and prefer single-quoting and htmlspecialchars(..., ENT_QUOTES) in any custom rendering you add. If you fork, add a test for it.

Groups and nested constraints are not traversed. Valid traversal into embedded objects, @Group-conditional constraints, and When/callback constraints are where client/server parity is most likely to break in both directions. Treat these fields as server-validated only and say so in the coverage table.

Regex is not portable by default. PHP PCRE and JS RegExp differ on lookbehind support, \A/\z anchors, and u-mode unicode. Any Regex constraint you expose to Parsley must be verified against JS semantics, or kept server-only.

jQuery dependency. Parsley is a jQuery plugin. If the app doesn't already ship jQuery, this is a real transitive cost — flag it explicitly rather than letting it leak in through Parsley.

Re-initialize after DOM mutations. Dynamically added fields (collections, AJAX-loaded fragments) need $(formEl).parsley() called again, or ParsleyForm re-binding. A common "it stopped validating" bug.

No-JS and accessibility. With JS disabled, only server validation runs — confirm the form still submits and errors render server-side. For a11y, wire Parsley's error events into aria-invalid and an aria-live region announcing errors; the default Parsley error DOM is not screen-reader-friendly out of the box.

CSP. Parsley's default error insertion may require unsafe-inline for styles or an allowance for its DOM manipulation — check against your CSP before rollout rather than during it.

Pin and own it. Last release was 2023-12-15 with a single maintainer and zero dependents. Pin the version, vendor or fork via Composer (repositories with a VCS path), and assign a named owner for the fork. Plan on Symfony major-version upgrades breaking this — assume you fix it yourself.

Version checks before committing. Confirm the Symfony major version the bundle supports (likely 5/6, given the release date), the PHP floor (attributes imply 8.0+), and the Parsley major version your front end loads. The composer.json was not inspected — read it before scheduling work.

Debugging shortcut. When a field "isn't validating," inspect the rendered HTML first: is the data-parsley-* attribute actually present? If not, the constraint didn't map (or groups filtered it out). Then check $(form).parsley().isValid() in the console. That ordering resolves most reports in under a minute.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource