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

Validation Bundle Laravel Package

respect/validation-bundle

A Symfony bundle that integrates the Respect\Validation library, exposing its expressive validation rules as container services for easy use in Symfony applications. Wire validators into your services and validate data with Respect's fluent, readable rule syntax.

View on GitHub
Deep Wiki
Context7

Getting Started

Treat respect/validation-bundle as reference material only — it's a Symfony bundle, and Laravel won't boot the extension, register its service, or read its config. Do not composer require respect/validation-bundle in a Laravel app; expect Composer conflicts on symfony/* transitive packages and no return on the extra layer.

What you actually install:

composer require respect/validation

Where to look first (clone the repo, read, don't install):

  • Validator/Constraints/Respect.php — the constraint class. It shows how a Validatable is wrapped and which options survive (message, groups). This is the shape your Laravel Rule will mirror.
  • Validator/Constraints/RespectValidator.php — the money file. It demonstrates the exception-to-message conversion: catching Respect\Validation\Exceptions\ValidationException and NestedValidationException, then walking getMessages() (flat) vs getFullMessage() (recursive) to produce violations. Port this logic, don't reinvent it.
  • DependencyInjection/Configuration.php — usually just an enabled toggle. Nothing you can't replicate with a single service binding.
  • The bundle's services.*.yml — shows how Respect\Validation\Validator was registered as a shared service. In Laravel that's one singleton() in a provider.

First use case — a high-value rule Laravel doesn't ship (IBAN, CPF/CNPJ, tax ID, credit card Luhn):

// app/Rules/Iban.php
namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Respect\Validation\Exceptions\ValidationException;
use Respect\Validation\Validatable;

class Iban implements ValidationRule
{
    public function __construct(private readonly Validatable $rule) {}

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        try {
            $this->rule->assert($value);
        } catch (ValidationException $e) {
            $fail('validation.iban')->translate();
        }
    }
}

Use it inside a FormRequest or a rule array:

'iban' => ['required', 'string', new Iban(v::iban())],

Confirm respect/validation supports your PHP version in its own composer.json before committing — the library is healthy, but pin a minor you've tested.

Implementation Patterns

One Rule wrapper, many Respect rules. The wrapper above is the only Laravel-specific code you write. Everything else — combinator rules, nested keys, length bounds — lives in respect/validation and flows through the same class. Do not write one Laravel Rule per Respect rule; pass the rule in.

Rule factory behind a service. Don't scatter v:: calls across controllers. Centralize in a small provider so the identical rule drives forms, API payloads, and queue jobs:

// app/Support/Validation/Rules.php
final class Rules
{
    public static function email(): Validatable
    {
        return v::stringType()->email()->length(null, 254);
    }

    public static function quantity(): Validatable
    {
        return v::intVal()->positive()->between(1, 100);
    }
}

Bind it, or make it static — either works; the point is that "what an email is" is defined once.

Composed rules for cross-field and nested data. This is where Respect beats Illuminate\Validation for DTOs and API payloads:

v::key('start', v::dateTime()->lessThanOrEqual(v::key('end')))
 ->key('end',   v::dateTime());

Then wrap with new RespectRule($rule) in a form request, or call it directly in a DTO hydrator. Cross-field after: callbacks become declarative.

Programmatic validation outside HTTP. For DTOs, import files, and queue message envelopes, use Respect directly with a small helper that maps exceptions:

  • ->assert($value) throws.
  • ->validate($value) returns bool (no message).
  • NestedValidationException::getFullMessage() gives a tree you can flatten into a Laravel error bag by path.

For a Rule-shaped DTO validator, reuse the same Iban-style wrapper and loop the fields; do not re-implement messages per surface.

Nested / array-of-structs. Combine Rule::forEach() (Laravel's iteration) with a Respect rule per element, or use Respect's v::each() and v::key() on associative payloads. Keeping element-level rules in the factory means the JSON API and the DB importer share behavior.

Testing. Respect rules are plain objects with no container footprint — unit-test them without booting Laravel. Test the wrapper separately with a fake Closure $fail to assert the translated message key. That's two fast, cheap test layers instead of a fixture-heavy feature test.

Bridging Rule::when / Rule::requiredIf. Laravel's conditional rules still work around your custom Rule; keep conditional presence in Illuminate\Validation, and leave value shape to Respect. Don't try to express "required if other field is X" inside Respect.

Gotchas and Tips

Do not install the Symfony bundle. This is the pitfall that costs the most time. Even if it resolves, config/bundles.php doesn't exist in Laravel, the DI extension won't fire, and you'll have a dependency that does nothing but drag symfony/dependency-injection into vendor/. The bundle is a pattern, not a runtime dependency — document that decision in the PR so a new hire doesn't try again.

Exception classes differ from Laravel's. Respect\Validation\Exceptions\ValidationException is not Illuminate\Validation\ValidationException. Your wrapper must catch the Respect class and call $fail(). If you let the Respect exception escape, it bubbles as a 500 — a subtle failure that only appears on the bad path, so write the test for the invalid case first.

NestedValidationException vs flat. getMessages() returns a nested array keyed by path; getFullMessage() returns a string with indentation. For array validation you want the tree so you can re-key into attribute.0.field in Laravel's error bag. Do this translation in the wrapper, once, and every rule benefits.

Message placeholders don't line up. Respect templates use {{name}}, {{input}}, {{sample}}; Laravel uses :attribute, :value. Don't try to make them interchangeable — pick Respect's templates for its built-in messages and pass Laravel translation keys ('validation.iban') through ->translate() in the fail closure. Mixing the two produces garbled messages in production and confusion in tests.

No translation wiring. The bundle leaned on Symfony's translator; Laravel's is a different shape. If you need localized Respect messages, define the key in lang/en/validation.php yourself and let the wrapper reference it. Don't expect v:: messages to localize automatically — they won't.

v::optional() and missing keys. v::optional() treats an absent key as valid but a present empty string as invalid. If a field is optional in your payload, wrap at the array level with v::key('foo', v::optional(...)) rather than at the value level — otherwise validators fire on missing keys and produce spurious violations.

Don't mix the two stacks per field. Pick a surface: Illuminate\Validation for presence/format rules that Laravel ships well, Respect wrapped in a Rule for the domain-specific or international rules. Two validators on the same attribute produce divergent messages and double failures in the error bag.

Static-analysis type is Validatable, not Validator. Validator::X() returns Respect\Validation\Validatable. Type your rule factories and wrapper constructors against the interface so ->assert() is available and PHPStan/Psalm stop complaining. Use v:: only inside factories.

Composer constraint hygiene. Since you depend on the library directly, respect/validation follows its own release cadence — check composer why respect/validation after any Laravel upgrade. It's framework-agnostic and rarely conflicts, but a ^3.x vs ^2.x bump changes exception methods (getMessages() shape), so pin your wrapper's tests to the version in composer.lock.

Extension point. Custom Respect rules live under Respect\Validation\Rules\ (extend AbstractRule, implement validate). Add them there rather than as Laravel Rule classes — they become reusable, testable, and composable with v::allOf() etc., which is the whole point of adopting the library. Reserve the Laravel Rule wrapper for the one place you must (the validate($attribute, $value, $fail) contract).

When in doubt, drop to Laravel. If the rule is 'email', 'required', 'in:a,b,c', 'max:255', use Illuminate\Validation. Respect earns its keep on the cross-field, nested-payload, and international-compliance rules; using it as a general-purpose replacement for Laravel's validator adds a second dialect, a second message layer, and maintenance drag for no gain.

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