Unlike traditional array-based rules scattered across controllers and form requests, this package introduces standalone and model-aware ruleset classes with support for:
- Rule reuse and extension via class inheritance
- Fluent rule composition within rulesets
- Centralized rules, messages, and attributes
- Seamless integration with Laravel’s native validator
- Ruleset management via Artisan make and list commands
This abstraction addresses the growing complexity and duplication in large Laravel codebases, where validation rules often become deeply nested, repetitive, or context-specific.
By shifting validation into dedicated, composable classes, Laravel Ruleset Validation enables clean architecture, code reuse, and a more scalable approach to application validation.
| Laravel Versions | Ruleset Validation Version | PHP Version |
|---|---|---|
| ≥ 9.x | 1.x | ≥ 8.2 |
- Installation
- Quickstart
- Defining Rulesets
- Validating Rulesets
- Extending Rulesets
- Fluent RuleBuilder
- Artisan Commands
- Configuration
- Package Utilities
- Testing
- Changelog
- Contributing
- Security
- License
composer require sjshovan/laravel-ruleset-validationOptionally publish config:
php artisan ruleset-validation:installuse App\Rulesets\UserRuleset;
use App\Models\User;
// Standard ruleset
$ruleset = UserRuleset::new();
$validated = $ruleset->validator([
'email' => 'foo@example.com',
'name' => 'Foo Bar',
])->validate();
// Model-aware ruleset
$user = User::find($id);
$validated = UserRuleset::for($user)->validator([
'email' => 'foo@example.com',
'name' => 'Foo Bar',
])->validate();Example usage for standard and model-aware rulesets.
Base classes for rulesets:
Sjshovan\RulesetValidation\Abstracts\BaseRuleset– standard rulesetsSjshovan\RulesetValidation\Abstracts\BaseModelRuleset– model-aware rulesets
use Sjshovan\RulesetValidation\Abstracts\BaseRuleset;
class UserRuleset extends BaseRuleset
{
public function rules(): array {
return $this->builder([
'email' => [Rule::email()->rfcCompliant(strict: false), 'max:64'],
'profession' => 'string',
'age' => 'int|min:12',
'weight' => 'int'
])
->add('name', 'string', 'min:4|max:32', ['not_in:hello,world'])
->remove('age', 'weight')
->prependAll('required')
->prepend('profession', 'sometimes')
->get();
}
public function messages(): array
{
return [
'email.max' => 'Your :attribute may not be greater than :max characters.',
];
}
public function attributes(): array
{
return [
'email' => 'email address',
];
}
}use App\Rulesets\UserRuleset;
$ruleset = UserRuleset::new();use Sjshovan\RulesetValidation\Abstracts\BaseModelRuleset;
use App\Models\User;
class UserPostRuleset extends BaseModelRuleset
{
public static function modelClass(): string
{
return User::class;
}
public function rules(): array
{
return [
'slug' => 'required|unique:posts,slug,' . $this->model()->id,
];
}
}use App\Rulesets\UserPostRuleset;
use App\Models\User;
$user = User::findOrFail($id);
$ruleset = UserPostRuleset::for($user);You can validate rulesets directly from the ruleset itself or by integrating with Laravel’s validator.
$validated = UserRuleset::new()->validator([
'email' => 'foo@example.com',
'name' => 'Foo Bar'
])->validate();All rulesets from the base abstracts include a validator() method, returning a fully configured Laravel validator.
Validator::makeFromRuleset(
UserRuleset::new(),
[...]
)->validate();Wraps Laravel’s existing Illuminate\Validation\Factory to add the makeFromRuleset() method.
- Preserves validator extensions regardless of when they were registered (before or after).
- Drop-in safe for existing apps.
Note: Disabled by default.
See Configuration for enabling instructions viafactory_decorator.
app(Factory::class)->makeFromRuleset(
UserRuleset::new(),
[...]
)->validate();Replaces Laravel’s Illuminate\Validation\Factory with the package’s RulesetFactory.
- Lets you type-hint
makeFromRuleset()directly. - Extensions work as long as they’re registered after the swap (e.g., in your app’s boot()).
Note: Disabled by default.
See Configuration for enabling instructions viafactory_concrete.
Provided tools for custom abstracts:
Sjshovan\RulesetValidation\Contracts\Ruleset– for standard rulesetsSjshovan\RulesetValidation\Contracts\ModelRuleset- for model-aware rulesetsSjshovan\RulesetValidation\Traits\IsRuleset– implementsRulesetcontractSjshovan\RulesetValidation\Traits\InstantiatesModel– adds model awarenessSjshovan\RulesetValidation\Traits\HasRuleBuilder– provides a rule builderSjshovan\RulesetValidation\Traits\HasRulesetValidator– provides a ruleset validator
Note: You can override default abstracts for
make:ruleset.
See Configuration for more details.
Intermediate abstracts allow you to define shared rules, messages, or attributes for multiple child rulesets.
namespace App\Rulesets\User;
use Sjshovan\RulesetValidation\Abstracts\BaseRuleset;
abstract class UserRulesetAbstract extends BaseRuleset
{
public function rules(): array {
return [
'email' => 'email|max:64',
'profession' => 'string',
'age' => 'int|min:12',
'weight' => 'int'
];
}
}
class CreateUserRuleset extends UserRulesetAbstract
{
public function rules(): array
{
return $this->builder(parent::rules())
->add('name', 'string', 'min:4|max:32', ['not_in:hello,world'])
->remove('age', 'weight')
->prependAll('required')
->prepend('profession', 'sometimes')
->get();
}
}The RuleBuilder lets you start with an empty or existing rules array and fluently add, modify, or remove rules. If you
extend the package’s base abstracts, you get a protected builder() method for free within child classes. You can also
instantiate it directly for external use.
use Sjshovan\RulesetValidation\RuleBuilder;
// Basic usage
$rules = RuleBuilder::new(['email' => 'required|string|email'])
->add('email', 'max:255')
->prepend('email', 'nullable')
->get();
// Merge and remove
$rules = RuleBuilder::new(['name' => 'required|string'])
->merge(['name' => ['max:50'], 'email' => 'nullable|email'])
->remove('name')
->get();
// Clear and reset
$rules = RuleBuilder::new(['email' => 'required|email'])
->clear()
->set('username', 'required')
->get();
// Prepend to all
$rules = RuleBuilder::new(['name' => 'string', 'email' => 'email'])
->prependAll('required')
->get();
// Conditional logic
$isAdmin = true;
$rules = RuleBuilder::new(['role' => 'string'])
->when($isAdmin, fn($b) => $b->add('role', 'in:admin,editor'))
->get();
// Return as a collection
$collection = RuleBuilder::new(['title' => 'required|string'])->collect();php artisan make:ruleset --help
Generates rulesets in the configured output path, optionally creating model-aware rulesets and intermediate abstracts.
# Standard ruleset
php artisan make:ruleset MyRuleset
# Model-aware ruleset
php artisan make:ruleset MyRuleset -mUser
# Generate intermediate abstract automatically
php artisan make:ruleset MyRuleset -g
# Dry run (output to console only)
php artisan make:ruleset MyRuleset -dIntermediate Abstract Behavior:
Enabled:
- Detects if ruleset is standard or model-aware.
- Searches for intermediate abstract.
- If missing, prompts to generate.
- If declined, extends the configured base abstract.
- If found, extends it automatically.
Disabled:
- Ruleset always extends the configured base abstract.
php artisan ruleset:list
Lists all rulesets in the configured output path, showing which are concrete or abstract, along with their namespaces.
# List all
php artisan ruleset:list
# Include Standard only
php artisan ruleset:list -s
# Include Model only
php artisan ruleset:list -m
# Include Abstract only
php artisan ruleset:list -a
# Include Concrete only
php artisan ruleset:list -c
# All (default)
php artisan ruleset:list -s -m -a -cExample output:
Publish the configuration file:
php artisan ruleset-validation:installThis creates config/ruleset-validation.php, where you can adjust:
-
paths — ruleset output directory and model discovery locations.
-
convention — default base abstract classes and suffix for ruleset names.
-
behavior — enable/disable the factory decorator, intermediate abstract generation, and suffix enforcement.
Default config:
<?php
return [
'paths' => [
'ruleset_output' => app_path('Rulesets'),
'model_discovery' => [app_path('Models')],
],
'convention' => [
'base_abstracts' => [
'ruleset' => \Sjshovan\RulesetValidation\Abstracts\BaseRuleset::class,
'model_ruleset' => \Sjshovan\RulesetValidation\Abstracts\BaseModelRuleset::class,
],
'ruleset_suffix' => 'Ruleset',
],
'behavior' => [
'factory_decorator' => false,
'factory_concrete' => false,
'convention' => [
'intermediate_abstracts' => true,
'ruleset_suffix' => true,
],
],
];Note: See the published config file for descriptions.
Sjshovan\RulesetValidation\Support\Package is a central utility class that consolidates configuration access, path
resolution, and stub generation for the package.
It provides:
-
Configuration access
- Reads from
config/ruleset-validation.php. - Retrieves paths, conventions, and behavior flags.
- Reads from
-
Stub management
- Loads stub files from the
/stubsdirectory. - Renders stubs with placeholder replacements for code generation.
- Loads stub files from the
-
Path resolution
- Resolves package-relative paths.
- Provides helpers for output directories and model discovery locations.
-
Behavior toggles
- Checks if the factory decorator is enabled.
- Determines suffix enforcement and intermediate abstract generation.
Note: This class is primarily intended for the package’s internal use. However, its helper methods are available if you find them useful in your own code.
composer testSee changelog.md for a list of changes.
See contributing.md for contribution guidelines.
If you discover any security issues, please see security.md.
This package is licensed under the MIT License. See license.md for details.


