{"id":13828232,"url":"https://github.com/illuminatech/validation-composite","last_synced_at":"2025-10-17T20:49:08.453Z","repository":{"id":56990024,"uuid":"191931731","full_name":"illuminatech/validation-composite","owner":"illuminatech","description":"Allows uniting of several validation rules into single one for easy re-usage","archived":false,"fork":false,"pushed_at":"2024-03-25T10:46:42.000Z","size":27,"stargazers_count":173,"open_issues_count":0,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-25T11:22:33.167Z","etag":null,"topics":["combine","composite","laravel","rule","validation","validator"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/illuminatech.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["klimov-paul"],"patreon":"klimov_paul"}},"created_at":"2019-06-14T11:27:22.000Z","updated_at":"2024-06-18T21:25:43.231Z","dependencies_parsed_at":"2024-06-18T21:25:41.925Z","dependency_job_id":"83becc86-4022-4389-ada4-9d62a17d5a5c","html_url":"https://github.com/illuminatech/validation-composite","commit_stats":{"total_commits":32,"total_committers":1,"mean_commits":32.0,"dds":0.0,"last_synced_commit":"c805d6185bd8efc98059fdee940b692f72c8d1f9"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Fvalidation-composite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Fvalidation-composite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Fvalidation-composite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/illuminatech%2Fvalidation-composite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/illuminatech","download_url":"https://codeload.github.com/illuminatech/validation-composite/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225492420,"owners_count":17482869,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["combine","composite","laravel","rule","validation","validator"],"created_at":"2024-08-04T09:02:37.623Z","updated_at":"2025-10-17T20:49:03.413Z","avatar_url":"https://github.com/illuminatech.png","language":"PHP","funding_links":["https://github.com/sponsors/klimov-paul","https://patreon.com/klimov_paul"],"categories":["PHP"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/illuminatech\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://avatars1.githubusercontent.com/u/47185924\" height=\"100px\"\u003e\n    \u003c/a\u003e\n    \u003ch1 align=\"center\"\u003eLaravel Composite Validation\u003c/h1\u003e\n    \u003cbr\u003e\n\u003c/p\u003e\n\nThis extension allows uniting several Laravel validation rules into a single one for easy re-usage.\n\nFor license information check the [LICENSE](LICENSE.md)-file.\n\n[![Latest Stable Version](https://img.shields.io/packagist/v/illuminatech/validation-composite.svg)](https://packagist.org/packages/illuminatech/validation-composite)\n[![Total Downloads](https://img.shields.io/packagist/dt/illuminatech/validation-composite.svg)](https://packagist.org/packages/illuminatech/validation-composite)\n[![Build Status](https://github.com/illuminatech/validation-composite/workflows/build/badge.svg)](https://github.com/illuminatech/validation-composite/actions)\n\n\nInstallation\n------------\n\nThe preferred way to install this extension is through [composer](http://getcomposer.org/download/).\n\nEither run\n\n```\nphp composer.phar require --prefer-dist illuminatech/validation-composite\n```\n\nor add\n\n```json\n\"illuminatech/validation-composite\": \"*\"\n```\n\nto the require section of your composer.json.\n\n\nUsage\n-----\n\nThe same sequence of the validation rules may repeat over the application many times. For example: you may have a set of\nrestrictions related to the user's password, like it should be at least 8 symbols long, but shorter then 200 to fit the\ndatabase field reserved for its storage. Your program may also allow user to upload an image to be his avatar, but in order\nto make it safe, you should validate uploaded file mime type and size.\nThus validation for the user profile form may looks like following:\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nuse Illuminate\\Http\\Request;\n\nclass ProfileController extends Controller\n{\n    public function update(Request $request)\n    {\n        $validatedData = $request-\u003evalidate([\n            'password' =\u003e ['required', 'string', 'min:8', 'max:200'],\n            'avatar' =\u003e ['required', 'file', 'mimes:png,jpg,jpeg', 'max:1024'],\n            // ...\n        ]);\n        \n        // ...\n    }\n}\n```\n\nThe problem is: validation for user's password or avatar may appear in several different places. For example: password\ncan be setup at sign-up process, during password reset and so on. You may also have a separated administration panel,\nwhich allows system administrator to adjust existing user's record or create a new one. Thus you will have to duplicate\nall these validation rules many times throughout your project source code. In case requirements change, for example:\nwe decide that password length should be at least 10 symbols instead of 8, or disallow '*.png' files from avatar - you'll\nhave to manually changes validation rules at all those places.\n\nThis extension allows uniting several validation rules into a single one for easy re-usage. For the example above you\nshould create 2 separated validation rule classes extending `Illuminatech\\Validation\\Composite\\CompositeRule`:\n\n```php\n\u003c?php\n\nnamespace App\\Rules;\n\nuse Illuminatech\\Validation\\Composite\\CompositeRule;\n\nclass PasswordRule extends CompositeRule\n{\n    protected function rules(): array\n    {\n        return ['string', 'min:8', 'max:200'];\n    }\n}\n\nclass AvatarRule extends CompositeRule\n{\n    protected function rules(): array\n    {\n        return ['file', 'mimes:png,jpg,jpeg', 'max:1024'];\n    }\n}\n```\n\nHere method `rules()` defines list of validation rules, which will be applied by defined rule internally.\nNow we can rewrite the form validation in following way:\n\n```php\n\u003c?php\n\nnamespace App\\Http\\Controllers;\n\nuse App\\Rules\\AvatarRule;\nuse App\\Rules\\PasswordRule;\nuse Illuminate\\Http\\Request;\n\nclass ProfileController extends Controller\n{\n    public function update(Request $request)\n    {\n        $validatedData = $request-\u003evalidate([\n            'password' =\u003e ['required', new PasswordRule],\n            'avatar' =\u003e ['required', new AvatarRule],\n            // ...\n        ]);\n        \n        // ...\n    }\n}\n```\n\nWith such approach you can change validation for the 'password' and 'avatar' at the single place.\n\nIn case composite validation rule fails, validator instance will pick up an error message from the particular sub-rule.\nFor example:\n\n```php\n\u003c?php\n\nuse App\\Rules\\PasswordRule;\nuse Illuminate\\Support\\Facades\\Validator;\n\n$validator = Validator::make(\n    ['password' =\u003e 'short'],\n    [\n        'password' =\u003e ['required', new PasswordRule],\n    ]\n);\n\nif ($validator-\u003efails()) {\n    echo $validator-\u003eerrors()-\u003efirst('password'); // outputs 'The password must be at least 8 characters.'\n}\n```\n\n\u003e Note: do not use rules like 'sometimes', 'required', 'required_with', 'required_without' and so on in the composite rule.\n  These are processed at the different validation level and thus will have no effect or may behave unexpectedly. \n\nYou may define composite validation rules using [validation factory extensions](https://laravel.com/docs/validation#using-extensions) feature.\nFor such case you may use `Illuminatech\\Validation\\Composite\\DynamicCompositeRule`. For example:\n\n```php\n\u003c?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Contracts\\Validation\\Factory;\nuse Illuminate\\Support\\ServiceProvider;\nuse Illuminatech\\Validation\\Composite\\DynamicCompositeRule;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        $this-\u003eapp-\u003eextend('validator', function (Factory $validatorFactory) {\n            $validatorFactory-\u003eextend('password', function ($attribute, $value) {\n                return (new DynamicCompositeRule(['string', 'min:8', 'max:200']))-\u003epasses($attribute, $value);\n            });\n            \n            $validatorFactory-\u003eextend('avatar', function ($attribute, $value) {\n                return (new DynamicCompositeRule(['file', 'mimes:png,jpg,jpeg', 'max:1024']))-\u003epasses($attribute, $value);\n            });\n\n            return $validatorFactory;\n        });\n        \n        // ...\n    }\n}\n```\n\nNote that with such approach automatic pick up of the validation error message becomes impossible, and you will have to setup\nit explicitly in language files.\n\nYou may specify [custom error messages](https://laravel.com/docs/validation#custom-error-messages) per each validation rule used in the composite one,\noverriding `messages()` method. For example:\n\n```php\n\u003c?php\n\nnamespace App\\Rules;\n\nuse Illuminatech\\Validation\\Composite\\CompositeRule;\n\nclass PasswordRule extends CompositeRule\n{\n    protected function rules(): array\n    {\n        return ['string', 'min:8', 'max:200'];\n    }\n\n    protected function messages(): array\n    {\n        return [\n            'string' =\u003e 'Only string is allowed.',\n            'min' =\u003e ':attribute is too short.',\n            'max' =\u003e ':attribute is too long.',\n        ];\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filluminatech%2Fvalidation-composite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filluminatech%2Fvalidation-composite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filluminatech%2Fvalidation-composite/lists"}