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

somnambulist/validation

Somnambulist Validation provides a Laravel-friendly validation toolkit for PHP, helping you define reusable rules and validate requests, forms, and application data through a clean, extensible API.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer:

composer require somnambulist/validation

There is no service provider or framework bootstrap; this is a standalone library. Start by reading the Factory class and the Rules/ directory in src/, since those define everything you can do out of the box. The Rule abstract class is the extension point for anything custom.

The smallest working flow is: build a factory, make a validator from an array of input and an array of rules, call validate(), then inspect fails() / passes() and errors():

use Somnambulist\Components\Validation\Factory;

$factory = new Factory();

$validator = $factory->make(
    ['name' => 'Ada', 'email' => '[email protected]', 'age' => 36],
    [
        'name'  => 'required|string|max:80',
        'email' => 'required|email',
        'age'   => 'required|integer|min:18',
    ]
);

$validator->validate();

if ($validator->fails()) {
    $errors = $validator->errors();       // ErrorBag
    $first  = $errors->first('email');    // first message for a field
    $all    = $errors->all();             // all messages
}

$clean = $validator->getValidatedData();  // only the validated keys

Your first real use case is almost always the same: you have a plain array of request data arriving from a controller, command handler, or importer, and you want Laravel-style rule strings and an error bag without pulling in the full framework.

Implementation Patterns

Register one Factory and reuse it. The factory is where messages, attribute labels, translations, and custom rules live. Constructing a new Factory per validation call works, but you lose configured messages and custom rules unless you re-register them. In a container, bind it as a singleton and configure it once in a bootstrap or service provider if you are inside a framework.

Keep rule sets in dedicated classes or config, not inline strings. A StoreUserRequest-style class that returns [data, rules, messages, attributes] keeps controllers thin and makes rules testable in isolation. The library does not provide a request abstraction, so this is your integration seam.

final class CreateUserRules
{
    public function rules(): array // ['email' => 'required|email|max:255', ...]
    public function messages(): array // ['email.required' => 'We need an email address.']
    public function attributes(): array // ['email' => 'email address']
}

Custom rules are the main extension path. Extend Somnambulist\Components\Validation\Rule (or implement the equivalent contract), give it a name, and register it on the factory with addRule(). This is how you validate domain invariants the built-in rules cannot express—unique SKUs, valid currency codes, allowed state transitions. Write a unit test per custom rule; they are pure input-to-boolean-with-message objects, which is exactly the shape you want in your test suite.

$factory->addRule('postcode', new PostcodeRule());

Use parameterized rule strings as the default. String syntax like 'required|between:1,10|regex:/^[A-Z]+$/' is compact and familiar to anyone who has used Laravel. Reach for array syntax only when a parameter contains a |.

Use wildcards and nested keys for arrays of inputs. Array rules like items.*.sku and items.*.qty are the reason this library exists in standalone form. Validate the whole payload in one pass rather than looping over rows in the controller.

Validate conditionally with sometimes / nullable combinations rather than branching in PHP. If a field only matters when another field is present, express that in rules; mixing conditional logic into the caller tends to produce validation that is hard to test and easy to bypass.

Return getValidatedData() downstream, not the raw input. Rules express intent; passing the validated subset to your handler prevents accidental reliance on unvalidated keys.

Map errors to your transport at the boundary. The ErrorBag is framework-agnostic. In a controller, convert it into a 422 JSON body (['errors' => $errors->all()] or per-field) or, in a server-rendered app, flash it into the session. Do not leak the bag into domain code.

Configure messages and attributes centrally. Locale-specific messages and human-readable attribute names belong in the factory configuration. A common pattern is to load message arrays from resources/lang/{locale}/validation.php-style files and feed them in during bootstrap.

Gotchas and Tips

Call validate() first. fails(), passes(), errors(), and getValidatedData() are meaningful only after validation has run. If you see empty errors where you expected failures, this is usually the cause.

The namespace is not Rakit\Validation. This is a rewrite, not a fork. When porting from rakit/validation, rewrite imports (Somnambulist\Components\Validation\...), check the factory-based construction instead of new Validator, and verify the message-key format before copying your existing message arrays across.

Message keys are rule-and-field specific, not just field-specific. A message map keyed only by field name will silently be ignored for some rules. Use field.rule style keys (e.g. email.required) and fall back to the default messages; if a custom message does not appear, the key is almost always the problem.

Attribute labels change messages, not validation. Setting an attribute alias (e.g. email => "email address") only affects the rendered message. It does not rename the key in the data or the error bag.

required semantics with 0, false, '', and null. These are separate cases and, depending on the rule you combine it with, may or may not count as "empty." If you are validating numeric fields that legitimately accept 0, add nullable/type rules deliberately and test the boundary.

The factory is stateful. Custom rules, messages, and translations are registered on it. If a rule works in one test but not another, check whether a fresh factory was created and whether the custom rule was re-registered. Prefer a single configured factory in tests.

Error bag accessors differ. first() returns the first message for a field, all() flattens everything. If you are rendering per-field errors in a template, iterate the bag's grouped form rather than relying on string matching against all().

Wildcard validation returns wildcard-expanded keys. Do not assume items.*.sku produces a flat result you can hand directly to an ORM. Inspect getValidatedData() shape in a test once when you first use wildcards, then build a small normalizer in your request class.

Custom rule parameters arrive as strings. Numeric thresholds coming from between:1,10-style syntax need casting if your rule performs strict comparisons. Validate the parameter count and types inside the rule constructor, not at validate time.

Regex rules need escaping in PHP strings. A pattern containing | will be split by the rule-string parser unless you quote or use the array rule syntax. This is the most common silent-failure mode with regex.

Rule ordering matters for performance and clarity. Cheap checks (required, string) first, expensive checks (database-backed custom rules) last. The library evaluates in the order written.

Extension points beyond custom rules are limited. If you need behavior not covered by a custom rule—cross-field validation with complex access to sibling fields, for example—write a dedicated rule class that receives the whole input array rather than trying to bend string syntax. Keep that logic in one place so it can be unit-tested without the factory.

No framework integration ships with the package. Laravel's validate() magic does not exist here. Budget a small amount of glue—request extraction, error response mapping, and factory bootstrapping—when you adopt it in Symfony, Slim, or plain PHP. That glue is the main upfront cost; after it exists, day-to-day usage is just "define rules, validate, return the clean data."

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.
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
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
cgv/localized-resource