{"id":37234209,"url":"https://github.com/xtompie/validation","last_synced_at":"2026-01-15T03:58:01.684Z","repository":{"id":57085206,"uuid":"433815534","full_name":"xtompie/validation","owner":"xtompie","description":null,"archived":false,"fork":false,"pushed_at":"2023-12-23T17:50:10.000Z","size":40,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-14T14:14:05.543Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xtompie.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-12-01T12:21:13.000Z","updated_at":"2022-11-18T09:12:43.000Z","dependencies_parsed_at":"2023-12-23T18:58:31.179Z","dependency_job_id":"f63c969e-e01b-4737-9fb4-a295513a8ce0","html_url":"https://github.com/xtompie/validation","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/xtompie/validation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Fvalidation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Fvalidation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Fvalidation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Fvalidation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xtompie","download_url":"https://codeload.github.com/xtompie/validation/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xtompie%2Fvalidation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28442357,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T00:55:22.719Z","status":"online","status_checked_at":"2026-01-15T02:00:08.019Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2026-01-15T03:58:01.006Z","updated_at":"2026-01-15T03:58:01.675Z","avatar_url":"https://github.com/xtompie.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Validation\n\nValidation component to validate models, input data.\nHandle any data types - arrays, objects, scalars, getter methods.\nEasy to extend.\nType hinting / autocompletion.\nFluent syntax.\n\n```php\nuse Xtompie\\Validation\\Validation;\n\n$result = Validation::of($input)\n    -\u003ekey('email')-\u003erequired()-\u003eemail()\n    -\u003ekey('password')-\u003erequired()-\u003emin(3)\n    -\u003egroup()\n    -\u003emain('password')-\u003ecallback(fn($input) =\u003e $input['email'] != $input['password'])\n    -\u003egroup()\n    -\u003ekey('email')-\u003ecallback(fn($email) =\u003e !inUse($email))\n    -\u003eresult();\n```\n\n`$result` is [`Xtompie\\Result\\Result`](https://github.com/xtompie/result)\n\n## Requiments\n\nPHP \u003e= 8.0\n\n## Installation\n\nUsing [composer](https://getcomposer.org/)\n\n```shell\ncomposer require xtompie/validation\n```\n\n## Docs\n\n### Subject\n\nValidation subject can be provided by\n\n```php\nValidation::of($input);\nValidation::new()-\u003ewithSubject($input);\nValidation::new()-\u003evalidate($input);\n```\n\n### Groups\n\n```php\nValidation::of($input)\n    /* Group 1 */\n    -\u003egroup()\n    /* Group 2 */\n    -\u003egroup()\n    /* Group 3 */\n    ;\n```\n\nIf an error occurs during group validation, subsequent groups will not be validated and validation will stop.\n\n### Targets\n\n```php\nValidation::new()\n    -\u003emain() // validation will target main subject\n    -\u003eproperty($name) // when subject is an object, will target property named $name\n    -\u003emethod($name) // when subject is an object, will target getter method named $name\n    -\u003ekey($key) // when subject is an array, will target array value where key is $key\n    -\u003etake($callback) // custom target $callback, as first argument main subject will be given\n;\n```\n\n### Nested Target\n\nTargets can be nested e.g.\n\n```php\n    $validation = Validation::of(['person' =\u003e ['name' =\u003e 'John']])\n        -\u003ekey('person')\n        -\u003enested()-\u003ekey('name')-\u003erequired()-\u003elengthMin(10)\n    ;\n    $validation-\u003eerrors()-\u003efirst()-\u003espace(); // person.name\n```\n\nAfter nested() function targets are related to last target.\nNested can be reset by `unested()`, `group()` or `main()` target.\nNested can be composed in multiple levels downwards\nSpace in error is automaticly generated.\n\n### Filters\n\nFilters are applied before validators\n\n```php\nValidation::new()\n    -\u003ekey('name')\n        -\u003efilter(fn($x) =\u003e ucfirst($x)) // custom callback filter\n        -\u003etrim()\n;\n```\n\n### Required/Optional\n\nTargets are optional by default. If target is required use required method.\n\n```php\nValidation::new()\n    -\u003ekey('name')-\u003erequired()\n;\n```\n\n### Validators\n\n```php\nValidation::new()\n    -\u003ekey('name')\n    // raw validator, validator return Result\n    -\u003evalidator(fn ($value) =\u003e strlen($value) !== 13 ? Result::ofSuccess() : Result::ofErrorMsg('Length can not be 13'))\n    // custom callback\n    -\u003ecallback(fn ($value) =\u003e strlen($value) !== 13, 'Length can not be 13')\n    -\u003enotBlank('Fill name!')\n;\n```\n\nAll list validator in source\n\n### Scalars\n\n```php\n$ok = Validation::of($email)-\u003erequired()-\u003eemail()-\u003esuccess();\n```\n\nIf no target is provided, then the main target, validation subject, will be used.\n\n### Validation feedback\n\n```php\n$v = Validation::new();\n$v-\u003eresult(); // Xtompie\\Result\\Result\n$v-\u003eerrors(); // Xtompie\\Result\\ErrorCollection\n$v-\u003eerror(); // ?Xtompie\\Result\\Error first error\n$v-\u003esuccess(); // bool\n$v-\u003efail(); // bool\n```\n\n### Extending\n\nComponent consists of 3 elements.\n\n1. ValidationValidator - builder and validator.\n2. ValidationCore - wrapper for the ValidationValidator. Gives fluent syntax, deals with validation subject.\n3. Validation - extends ValidationCore by inheritance. Gives concrete validations, filters, messages, keys.\n\n#### Inheritance\n\nValidation or ValidationCore can be extended by inheritance.\n\n```php\n\nnamespace App\\Shared\\Validation;\n\nuse App\\Shared\\Dao\\Dao;\nuse Xtompie\\Validation\\Validation as BaseValidation;\n\nclass Validation extends BaseValidation\n{\n    public function __construct(\n        protected Dao $dao,\n    ) {}\n\n    protected function msgs(): array\n    {\n        return array_merge(parent::msgs(), [\n            'dao_not_exists' =\u003e 'Value {value} already exists',\n        ]);\n    }\n\n    public function trim(): static\n    {\n        return $this-\u003efilter(fn($v) =\u003e trim($v));\n    }\n\n    public function digit($msg = 'Only digits allowed', $key = 'digit'): static\n    {\n        return $this-\u003evalidator(fn($v) =\u003e ctype_digit($v) ? Result::ofSucces() : Result::ofErrorMsg($msg, $key));\n    }\n\n    public function daoNotExists(string $table, string $field, ?string $exceptId = null, ?string $msg = null)\n    {\n        return $this-\u003evalidator(fn ($v) =\u003e $this-\u003etest(\n            !$this-\u003edao-\u003eexists($table, [$field =\u003e $v, 'id !=' =\u003e $exceptId]),\n            'dao_not_exists',\n            $msg,\n            ['{value}' =\u003e $v]\n        ));\n    }\n}\n\nnamespace App\\User\\Application\\Service;\nuse App\\Shared\\Validation\\Validation;\n\nclass CreateUserService\n{\n    public function __construct(\n        protected Validation $validation,\n    ) {}\n\n    public function __invoke(string $email): Result\n    {\n        $result = $this-\u003evalidation-\u003ewithSubject($email)\n            -\u003erequired()\n            -\u003eemail()\n            -\u003edaoNotExists('user', 'email')\n        ;\n        if ($result-\u003efail()) {\n            return $result;\n        }\n\n        // create user\n\n        return Result::ofSuccess();\n    }\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxtompie%2Fvalidation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxtompie%2Fvalidation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxtompie%2Fvalidation/lists"}