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

Validator Laravel Package

toa/validator

toa/validator is a PHP validation package for Laravel applications, offering a structured way to define and apply validation rules. It integrates with Laravel's validation workflow, helping developers keep request and data validation organized and reusable.

View on GitHub
Deep Wiki
Context7

Getting Started

toa/validator is a Symfony-Validator-inspired component with effectively zero public adoption (0 stars, 0 dependents). That single fact should shape your whole approach: the source and tests are the documentation, not the README, and not Symfony's docs.

Minimal steps

  1. composer require toa/validator, then commit composer.lock and pin the exact version in composer.json. Do not use a floating constraint on a package nobody else is exercising.
  2. Read composer.json first — check the PHP version constraint, whether it pulls in a translator, a PSR container, or annotation/attribute parsing libraries. Those transitive dependencies often reveal more about the design than the README does.
  3. Read src/ top-down. You are looking for four things:
    • the entry point (likely a Validator class with a validate() method),
    • the Constraint base class and how options are passed to it,
    • the constraint-validator contract (Symfony calls this ConstraintValidatorInterface),
    • the error/result object returned from validate().
  4. Read tests/ next. For a package at this maturity, the test suite is the most accurate record of intended usage and edge-case behavior.

First use case — validate an inbound payload before it reaches a service:

use Toa\Validator\Validator;
use Toa\Validator\Constraint as Assert; // confirm namespace in src/

$validator = new Validator(); // constructor signature varies — check src/Validator.php

$errors = $validator->validate($payload, [
    new Assert\NotBlank(['message' => 'Email is required']),
    new Assert\Email(),
    new Assert\Length(['min' => 3, 'max' => 255]),
]);

if (count($errors) > 0) {
    // Inspect the error object first: getMessage(), getPropertyPath(),
    // or array access — the shape is package-specific.
}

Before wiring this into a controller, spend ten minutes confirming the result object's API. Whether validate() returns an array, an ErrorList, or a traversable determines how you format 422 responses, and guessing here produces the most common early bug.

Define the boundary immediately. Create one ValidationService interface in your application and one adapter class that wraps toa/validator. Every call site depends on your interface, never on the package's classes. Given the adoption risk, this is the cheapest possible insurance policy — if the package stalls, you rewrite one adapter and swap in symfony/validator, which this package is explicitly modeled on.

Implementation Patterns

Per-field constraint maps. The natural fit for request validation is a map of field name to constraint list, applied in a loop:

$rules = [
    'email'    => [new Assert\NotBlank(), new Assert\Email()],
    'password' => [new Assert\NotBlank(), new Assert\Length(['min' => 8])],
];

$errors = [];
foreach ($rules as $field => $constraints) {
    $result = $validator->validate($payload[$field] ?? null, $constraints);
    if (count($result) > 0) {
        $errors[$field] = $result; // normalize into your own error shape here
    }
}

Flattening into your own array structure at the boundary keeps the package's error objects from leaking into views, API responses, and tests.

Custom constraint + validator pair. This is where the Symfony lineage pays off. You define a constraint class (a value object holding options/messages) and a validator class (the logic), then register the association. Look at how existing constraints in src/ declare their validator — via a validatedBy()-style method, an attribute, or a registry — and copy that exact mechanism. Do not assume the Symfony registration path works.

final class Uuid extends Assert\Constraint
{
    public string $message = 'Invalid UUID.';
}

final class UuidValidator // implements the package's validator contract
{
    public function validate($value, Uuid $constraint): void
    {
        if ($value !== null && !preg_match('/^[0-9a-f]{8}-/i', $value)) {
            // report violation via whatever API the package exposes
        }
    }
}

Nested and collection validation. If the package supports cascading into objects, verify it with a three-line test before relying on it in a domain model. If it does not, do not build deep object-graph validation on top of it — validate at the edges (arrays/DTOs) and let your domain enforce its own invariants. This is a better architecture anyway and avoids depending on an unproven traversal implementation.

Conditional and grouped rules. Symfony-style groups are useful for "validate on create" vs "validate on update". Check whether groups are actually implemented or just named in the API. If they are stubbed, model conditions in plain PHP — build a different constraint array per scenario — rather than fighting a half-implemented feature.

Test fixtures. Write a small ValidatorFactory helper for tests that returns a configured validator instance. Because the constructor signature and dependencies (translator? container?) are package-specific, centralizing construction keeps your test suite stable if you later swap implementations.

Integration point. Wire validation into a form-request or middleware layer, not into controllers directly, and return a consistent error payload. Keep the adapter's surface narrow: validate(array $data, array $rules): array returning plain arrays is usually the entire API you need.

Gotchas and Tips

Symfony documentation will mislead you. The package is inspired by Symfony, not compatible with it. Class names, option keys, the error API, and constraint registration may all differ. Every assumption must be checked against src/ or tests/. Copying a Symfony snippet and fixing namespaces is a reliable way to burn an afternoon.

No community support means no bug oracle. With zero dependents, you are likely the first person to hit any given bug. Budget for reading the implementation when something behaves oddly, and add a regression test in your suite for every quirk you discover — upstream fixes may never arrive.

Null vs empty string semantics. Constraint chains usually treat null as "skip unless NotBlank" and '' differently. Test both explicitly for each constraint you adopt. This is the single most common source of validation mismatches in Symfony-derived libraries.

Constructor and dependency coupling. If Validator requires a translator or a container at construction, instantiate it once and inject it — do not build it per request. Also check whether messages are translated by default; if a translator is required but optional, missing it may silently swallow messages or throw.

Attributes vs annotations. If the package supports metadata-driven validation, confirm which PHP versions and which mechanism (docblock annotations need a parser dependency; attributes need PHP 8+). If metadata support is partial, prefer explicit constraint arrays — they are greppable, testable, and immune to reflection quirks.

Error object mutability and shape. Some implementations return mutable violation lists that accumulate if you reuse the validator instance across a loop. Validate that a fresh call returns a fresh result, or reset explicitly. Normalize to arrays immediately so downstream code never touches package objects.

Pin, wrap, and plan the exit. Pin the version, keep the adapter as the only integration point, and write one integration test that runs the adapter end-to-end. If the package becomes unmaintained, that single test plus the adapter is your migration checklist to symfony/validator — whose API this package mirrors closely enough that the swap should be mechanical.

Extension points worth knowing. Identify early whether the package exposes a way to register custom validators globally, override messages, or hook error formatting. Those are the levers you will need most often in day-to-day work, and in a low-adoption package they are sometimes the least documented part of the code.

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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core