korridor / laravel-model-validation-rules
A laravel validation rule that uses eloquent to validate if a model exists
Installs: 93 911
Dependents: 0
Suggesters: 0
Security: 0
Stars: 25
Watchers: 4
Forks: 5
Open Issues: 0
Requires
- php: >=8.1
- illuminate/database: ^10|^11
- illuminate/support: ^10|^11
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.6
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10
- squizlabs/php_codesniffer: ^3.5
README
This package is an alternative to the Laravel built-in validation rules exists
and unique
.
It uses Eloquent models instead of directly querying the database.
Advantages
- The rule can be easily extended with the Eloquent builder. (scopes etc.)
- Soft deletes are working out of the box.
- Logic implemented into the models work in the validation as well. (multi tenancy system, etc.)
Note
Check out solidtime - The modern Open Source Time-Tracker at solidtime.io
Installation
You can install the package via composer with following command:
composer require korridor/laravel-model-validation-rules
If you want to use this package with older Laravel/PHP version please install the 2.1.* version.
composer require korridor/laravel-model-validation-rules "^2.1"
Requirements
This package is tested for the following Laravel and PHP versions:
- 10.* (PHP 8.1, 8.2, 8.3)
- 11.* (PHP 8.2, 8.3)
Usage examples
PostStoreRequest
use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent; use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent; // ... public function rules(): array { $postId = $this->post->id; return [ 'username' => [new UniqueEloquent(User::class, 'username')], 'title' => ['string'], 'content' => ['string'], 'comments.*.id' => [ 'nullable', new ExistsEloquent(Comment::class, null, function (Builder $builder) use ($postId) { return $builder->where('post_id', $postId); }), ], 'comments.*.content' => ['string'] ]; }
PostUpdateRequest
use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent; use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent; // ... public function rules(): array { $postId = $this->post->id; return [ 'id' => [new ExistsEloquent(Post::class)], 'username' => [(new UniqueEloquent(User::class, 'username'))->ignore($postId)], 'title' => ['string'], 'content' => ['string'], 'comments.*.id' => [ 'nullable', new ExistsEloquent(Comment::class, null, function (Builder $builder) use ($postId) { return $builder->where('post_id', $postId); }), ], 'comments.*.content' => ['string'] ]; }
Custom validation message
If you want to change the validation message for one specific case, you can use the withMessage(...)
function to add a custom validation message.
With withCustomTranslation(...)
you can set a custom translation key for the validation message.
As described in detail in the next example (Customize default validation message), it is possible to use :attribute
, :model
and :value
in the translation.
use Korridor\LaravelModelValidationRules\Rules\UniqueEloquent; use Korridor\LaravelModelValidationRules\Rules\ExistsEloquent; // ... public function rules(): array { $postId = $this->post->id; return [ 'id' => [(new ExistsEloquent(Post::class))->withMessage('The ID already exists.')], 'username' => [ (new UniqueEloquent(User::class, 'username')) ->ignore($postId) ->withCustomTranslation('validation.custom.username.unique_eloquent') ], 'title' => ['string'], 'content' => ['string'], 'comments.*.id' => [ 'nullable', new ExistsEloquent(Comment::class, null, function (Builder $builder) use ($postId) { return $builder->where('post_id', $postId); }), ], 'comments.*.content' => ['string'] ]; }
Customize default validation message
If you want to customize the translations of the default validation errors you can publish the translations
of the package to the resources/lang/vendor/modelValidationRules
folder.
php artisan vendor:publish --provider="Korridor\LaravelModelValidationRules\ModelValidationServiceProvider"
You can use the following attributes in the validation message:
attribute
model
value
return [ 'exists_model' => 'A :model with the :attribute ":value" does not exist.', 'unique_model' => 'A :model with the :attribute ":value" already exists.', ];
Example outputs would be:
A user with the id "2" does not exist.
A user with the id "2" already exists.
Contributing
I am open for suggestions and contributions. Just create an issue or a pull request.
Local docker environment
The docker
folder contains a local docker environment for development.
The docker workspace has composer and xdebug installed.
docker-compose run workspace bash
Testing
The composer test
command runs all tests with phpunit.
The composer test-coverage
command runs all tests with phpunit and creates a coverage report into the coverage
folder.
Codeformatting/Linting
The composer fix
command formats the code with php-cs-fixer.
The composer lint
command checks the code with phpcs.
Credits
The structure of the repository and the TestClass is inspired by the project laravel-validation-rules by spatie.
License
This package is licensed under the MIT License (MIT). Please see license file for more information.