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

runn/validation

A Laravel validation package that extends the framework's built-in validator with additional rules and helpers, making it easier to define and reuse custom validation logic across your application's forms and requests.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and pin.

composer require runn/validation

Check the composer.json PHP constraint before you commit. This is a PHP 7-era library with a single maintainer and almost no downstream usage, so pin an exact version ("runn/validation": "1.x.x" or a commit hash) rather than floating on ^.

2. Read the source, not the docs. There is no documentation site and the README is thin. The spec lives in src/ plus the tests/ folder. Spend ten minutes in this order:

  • src/ root — the Validator-style entry class and the error container / HasErrors trait.
  • src/Rules/ — the built-in rule catalogue (required/not-empty, string, int/float, email, regexp, length/range, in-array, callback). This is where you learn what you don't have to write yourself.
  • src/Interfaces/ (or Contracts/) — the Rule contract. Everything else (custom rules, adapters) hangs off this.
  • tests/ — the most reliable usage examples in the repo.

3. First use case: validate a flat request array. The library's sweet spot is taking an associative array ($_POST-shaped) and returning a boolean plus a keyed error bag.

use RunnMe\Validation\Validator;

$validator = new Validator([
    'email'    => [/* required, email */],
    'password' => [/* required, min length */],
    'age'      => [/* optional, int, min 18 */],
]);

if (! $validator->validate($input)) {
    $errors = $validator->errors(); // keyed by field name
}

Confirm the exact rule class names in src/Rules/ — they follow a short, predictable naming convention, so the autocomplete in your IDE is faster than guessing from the README.

Implementation Patterns

Rule-per-field maps, declarative config. The idiomatic pattern is a plain PHP array mapping field name → one rule or an array of rules. Build these as static factory methods on a per-form class (LoginRules::class, SignupRules::class) so the rule map is testable in isolation and reusable between the API controller and the CLI command.

final class SignupRules
{
    public static function rules(): array
    {
        return [
            'email'    => [new Email()],
            'password' => [new NotEmpty(), new MinLength(8)],
        ];
    }
}

Sanitize first, validate second, then trust the types. The companion sanitization side of the package is the reason to pick this over hand-rolled filter_var calls. Run the sanitizer over the raw input, then validate the cleaned array, then hand the validated array to your domain layer. Doing it in the other order means your rules have to defend against " 42 " and null and "null" simultaneously.

Wrap it in a request/form object. Don't sprinkle new Validator(...) through controllers. One small class per form with validate(array $input): bool, errors(): array, and validated(): array keeps the library at one seam in your codebase — which matters enormously given the bus factor. If you ever swap to Laravel's or Symfony's validator, you rewrite one class.

$form = new SignupForm($request->all());
if (! $form->validate()) {
    return $this->json(['errors' => $form->errors()], 422);
}
$user = $this->users->create($form->validated());

Custom rules as the extension point. Anything the catalogue lacks — "unique email", "valid coupon code", "belongs to current tenant" — becomes a small class implementing the rule contract. Keep DB-touching rules out of the static rule map and inject the repository, or you'll end up with rules that can't be unit-tested without a database.

final class UniqueEmail implements Rule
{
    public function __construct(private UserRepository $users) {}

    public function validate($value, $data = null): bool
    {
        return $this->users->findByEmail((string) $value) === null;
    }
}

Pair it with your own exception at the boundary. The library returns errors; your app should throw. A ValidationFailedException carrying the error bag lets a single middleware translate it into a 422 response, and keeps controllers one-liner thin.

Test against the error keys, not the messages. Assert assertArrayHasKey('email', $errors) rather than matching English strings. Messages are the first thing you'll want to override, and message-coupled tests will break on day one of i18n.

Gotchas and Tips

The license is LGPL-3.0, not MIT. For a library consumed via Composer this is normally fine (dynamic linking), but if your legal team treats copyleft as a blocker, or if you plan to statically bundle/vendor the source into a distributed binary, resolve that before you build on it. This is the single most common reason teams bounce off this package.

Assume no PHP 8 guarantee. The package targets PHP 7. If you're on 8.1+, run the test suite of the package itself under your target version (composer test in a scratch clone) before adopting. Expect deprecation noise around implicitly nullable parameters, dynamic properties, and loose string/number comparisons in rules.

Validator instances are stateful. The error bag accumulates. Create a fresh validator per request, or explicitly clear it between uses — otherwise errors from a previous validation silently leak into the next response. This bites hardest in queue workers and long-running Swoole/RoadRunner processes.

Missing key ≠ null ≠ empty string. Decide up front which one means "not provided" for optional fields, and check how the required-style rule treats each. Most validator bugs in hand-rolled rule sets come from this single ambiguity, and this library won't resolve it for you.

Order your rules — don't assume short-circuiting. Put type/emptiness checks before anything that would fatal on the wrong type (preg_match against an array, arithmetic on a string). If the validator evaluates all rules rather than stopping at the first failure, a later rule can run on garbage input.

Messages are English and hard-coded in the rules. If you need Russian, German, or product-specific wording, plan to either subclass the rules to override messages, or map the error keys to your own translation catalogue at the response boundary. The latter is less invasive and survives package upgrades.

No Laravel/Symfony bridge exists. The integration is ~30 lines: a FormRequest-like wrapper, an exception, and a middleware. Write it yourself; don't hunt for a package that doesn't exist.

Debugging: when a rule unexpectedly passes, dump the sanitized input immediately before validation — nine times out of ten the sanitizer already coerced the value into something the rule accepts (e.g. "" → 0).

Exit strategy. With 10 stars, 0 dependents, and a single maintainer, treat this as a vendor risk. Keep the library behind the form-object seam described above, and if the project matters, fork it into your VCS and point Composer at the fork ("repositories": [{"type": "vcs", ...}]). You keep the API and gain the ability to patch a PHP 8.4 deprecation yourself.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route