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 Laravel Package

gal-digital-gmbh/validation

A Laravel package that extends the validator with reusable custom rules and helpers, making form and request validation cleaner and more consistent. Simple to install and configure, it helps centralize validation logic and reduce duplicated checks across controllers and form requests.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a thin convenience layer over symfony/validator, so the fastest way to get productive is to understand the underlying component first and then see what the wrapper removes. As of 2.0.0 it requires Symfony 6 (PHP 8.1+) and exposes a small, now-typed Validator class that proxies validate, validateProperty, validatePropertyValue, getMetadataFor and hasMetadataFor.

  1. Install it alongside the Symfony validator (the package will pull it in, but pin versions explicitly so you stay on Symfony 6):
    composer require gal-digital-gmbh/validation:^2.0 symfony/validator:^6.0
    
  2. Open vendor/gal-digital-gmbh/validation/src/ before writing any code. With zero stars and no documentation surface, the source is the documentation. Look for:
    • the factory/builder that constructs a ValidatorInterface (this is what you should reuse, not re-instantiate),
    • the Validator class itself — it is the whole public API and mirrors Symfony’s method names one-for-one, so there is little to learn beyond the method signatures,
    • any custom constraint classes,
    • how it registers metadata loaders (in 2.0.0 this is attributes only — Doctrine annotations are gone with Symfony 6).
  3. Configure it the same way you would configure Symfony’s ValidatorBuilder: enable attribute mapping, and register a translator if you want localized violation messages.
  4. First use case: validate a request/command DTO before it reaches your domain layer.
    use Symfony\Component\Validator\Constraints as Assert;
    
    final class CreateUserInput
    {
        public function __construct(
            #[Assert\NotBlank]
            #[Assert\Email]
            public readonly string $email = '',
            #[Assert\NotBlank]
            #[Assert\Length(min: 8)]
            public readonly string $password = '',
        ) {}
    }
    
    Then pass it through the package’s Validator (or the ValidatorInterface it exposes) and inspect the ConstraintViolationListInterface.

The first milestone should be: one DTO, one constraint set, one place in the codebase that turns violations into a 422/400 response. Once that loop works, everything else is repetition.

Implementation Patterns

DTO + attribute constraints, validated at the boundary. This is the highest-leverage pattern. Keep validation declarative on the DTO and let the package handle validator construction. Controllers, console commands, and queue consumers all call the same validator, so rules cannot drift between HTTP and CLI paths.

Reuse a single validator instance. Symfony’s validator caches constraint metadata, and building it per request is wasteful. If the package does not provide a container binding, register the factory output as a singleton in your service container and inject ValidatorInterface everywhere. In Laravel, that means a small service provider binding; in Symfony, an alias to the package’s service.

Normalize violations into a stable response shape early, so API clients do not depend on Symfony’s internal violation structure:

$errors = [];
foreach ($violations as $violation) {
    $errors[$violation->getPropertyPath()][] = $violation->getMessage();
}

Do this in one adapter class, not in every controller.

Use validateProperty / validatePropertyValue for partial updates. 2.0.0 makes these first-class typed methods on the package’s Validator, which is the cleanest way to handle PATCH semantics: validate only the fields present in the payload against the constraints declared on the DTO, instead of maintaining a parallel “update” DTO or a separate group set.

Use validation groups for context-dependent rules. A CreateUserInput and UpdateUserInput often share fields but differ on required-ness. Groups (#[Assert\NotBlank(groups: ['create'])]) plus $validator->validate($dto, null, ['create']) keep one DTO instead of two near-duplicates. getMetadataFor() is now typed and useful when you need to introspect which constraints exist for a class/group before validating.

Validate nested objects explicitly. For value objects or child DTOs, Symfony only cascades when the property is annotated with #[Assert\Valid]. If the package adds any “automatic deep validation,” verify it in a test — do not assume it.

Custom constraints for domain rules. When a rule needs a repository (uniqueness, existence), write a Constraint + ConstraintValidator pair and register the validator as a service so it can receive dependencies. This is the intended extension point and keeps the DTO free of service calls.

Validate arrays/maps with Collection and All. For JSON payloads that are not mapped to objects yet, new Assert\Collection([...]) with allowExtraFields: false is a quick way to harden an endpoint before a DTO exists.

Integrate at the edges only. Do not sprinkle $validator->validate() through domain services. Validate once at the entry point, then trust the typed object. Double validation makes failures hard to trace and couples your domain to the validator.

Wrap, don’t extend. Since 2.0.0 the package’s classes are final. Anything you previously did by subclassing Validator must become composition: your own class implementing ValidatorInterface (or a small decorator) that delegates to the package instance.

Gotchas and Tips

  • This is not Laravel’s validator. There is no $request->validate(), no required|email string syntax, and no ValidationException that redirects with old input. You are working with ConstraintViolationListInterface and must map it yourself. If the team expects Laravel semantics, that mismatch will cause friction.
  • 2.0.0 is a hard breaking release. It requires Symfony 6 and PHP 8.1+, makes all classes final, and adds native parameter types to validate, validateProperty, validatePropertyValue, getMetadataFor and hasMetadataFor. Pin ^2.0 and budget an upgrade task: any subclass of the package’s Validator breaks outright, and callers that previously relied on loose coercion (e.g. passing a string where an object/array is expected) will now get a TypeError instead of a silent pass.
  • Final classes cannot be mocked. PHPUnit cannot double a final class. If your tests mocked the package’s Validator directly, switch to injecting and mocking Symfony\Component\Validator\Validator\ValidatorInterface, or test through a real validator instance. This is the most likely place the upgrade breaks a green test suite.
  • Attributes only. Symfony 6 dropped Doctrine annotation mapping, and 2.0.0 is built against it. If any part of the codebase still declares constraints via annotations (@Assert\NotBlank in docblocks), they will be silently ignored and validation will always pass. Grep for @Assert during the upgrade.
  • Localization needs symfony/translation. Without a translator wired into the builder, violation messages fall back to English keys. If the product is German-facing (likely, given the vendor), set the translator’s locale explicitly and test one message end-to-end.
  • Valid is not implicit. Nested DTOs will pass even when their inner fields are invalid unless the parent property carries #[Assert\Valid]. This is the single most common “validation is broken” report with Symfony’s validator.
  • Empty vs. missing. NotBlank rejects empty strings; NotNull does not. Length ignores null unless combined with NotBlank. Get these combinations right in tests, because they behave differently from Laravel’s required.
  • Groups and the default group. Constraints without an explicit group belong to Default. Calling validate($dto, null, ['create']) will not run Default constraints unless you include it. This surprises people constantly.
  • Metadata cache in long-running processes. Under Octane, Swoole, or queue workers, verify that the validator (and its metadata cache) is rebuilt on deploy. Stale metadata after a constraint change looks like a phantom bug.
  • Still audit the package before depending on it. Zero stars and zero dependents mean it is effectively an internal utility published publicly. 2.0.0 is a maintenance release — tooling bumps, final, and type declarations — not a feature release, which tells you the upstream author is keeping it healthy but not growing it. Read the source, check the composer.json for the supported Symfony/PHP range, and consider whether a ~50-line internal factory around Validation::createValidatorBuilder() gives you the same convenience with one less dependency. If you adopt it, pin the version and add a test that locks in the violation behavior you rely on.
  • Extension points to prefer: the factory (to add custom loaders/translators), validateProperty/validatePropertyValue for partial payloads, and custom ConstraintValidator services. With classes now final, subclassing is no longer an option — anything you need beyond those is usually a sign you should call Symfony’s validator directly.
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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk