├── Facades └── Validator.php ├── Factory.php ├── Helper ├── BaseExtComponentGetter.php ├── ConfigHelper.php └── ExtComponentGetter.php ├── Install.php ├── Mock └── LaravelDb.php ├── README.md ├── Translation ├── NullTranslator.php └── WebmanSymfonyTranslator.php ├── composer.json ├── copy ├── config │ └── plugin │ │ └── app.php └── resource │ └── translations │ ├── en │ └── validation.php │ └── zh_CN │ └── validation.php └── helper.php /Facades/Validator.php: -------------------------------------------------------------------------------- 1 | setPresenceVerifier($dbPresence); 64 | } 65 | // registerUncompromisedVerifier 涉及到需要远程调用api,暂时不考虑 66 | 67 | return $factory; 68 | } 69 | 70 | protected static function createDatabasePresenceVerifier(): ?DatabasePresenceVerifierInterface 71 | { 72 | return ExtComponentGetter::get(DatabasePresenceVerifierInterface::class); 73 | } 74 | 75 | public static function getTranslator(): TranslatorContract 76 | { 77 | return ExtComponentGetter::get(TranslatorContract::class); 78 | } 79 | 80 | /** 81 | * @param $name 82 | * @param $arguments 83 | * @return mixed 84 | */ 85 | public static function __callStatic($name, $arguments) 86 | { 87 | return static::instance()->{$name}(... $arguments); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Factory.php: -------------------------------------------------------------------------------- 1 | getTranslator()->setLocale(locale()); 17 | } 18 | 19 | return parent::make($data, $rules, $messages, $attributes); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Helper/BaseExtComponentGetter.php: -------------------------------------------------------------------------------- 1 | $options) { 24 | $ids = array_merge([$className], $options['alias'] ?? []); 25 | $componentGetter = null; 26 | foreach ($ids as $id) { 27 | if (Container::has($id)) { 28 | $componentGetter = fn() => Container::get($id); 29 | break; 30 | } 31 | } 32 | if ($componentGetter === null) { 33 | $componentGetter = $options['singleton'] ?? null; 34 | } 35 | if ($componentGetter === null) { 36 | throw new \InvalidArgumentException('cannot find component ' . $className); 37 | } 38 | // 将所有 id 注册为组件 39 | foreach ($ids as $id) { 40 | self::$componentsDefine[$id] = [$ids, $componentGetter]; 41 | } 42 | } 43 | } 44 | 45 | return self::$componentsDefine; 46 | } 47 | 48 | /** 49 | * @template T of class-string|string 50 | * @param T $need 51 | * @return (T is class-string ? T|null : mixed) 52 | */ 53 | public static function get(string $need) 54 | { 55 | $component = self::$components[$need] ?? null; 56 | if ($component) { 57 | return $component === '__NULL__' ? null : $component; 58 | } 59 | 60 | $componentDefine = self::getDefinedComponents()[$need] ?? null; 61 | if ($componentDefine === null) { 62 | throw new \InvalidArgumentException($need . ' is not defined'); 63 | } 64 | 65 | [$ids, $componentGetter] = $componentDefine; 66 | $component = $componentGetter(); 67 | if ($component === null) { 68 | $component = '__NULL__'; 69 | } 70 | // 将所有相关组件都注册上 71 | foreach ($ids as $id) { 72 | self::$components[$id] = $component; 73 | } 74 | 75 | return $component; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Helper/ConfigHelper.php: -------------------------------------------------------------------------------- 1 | [ 28 | 'alias' => ['translator'], 29 | 'singleton' => function () { 30 | if (class_exists(Translator::class)) { 31 | return Translator::instance(); 32 | } 33 | if (class_exists(SymfonyTranslator::class)) { 34 | return new WebmanSymfonyTranslator(); 35 | } 36 | return new NullTranslator(); 37 | }, 38 | ], 39 | /** @see DatabaseServiceProvider::registerConnectionServices() */ 40 | ConnectionResolverInterface::class => [ 41 | 'alias' => ['db'], 42 | 'singleton' => function () { 43 | if (class_exists('Illuminate\Database\Capsule\Manager') && class_exists('support\Db')) { 44 | return LaravelDb::getInstance()->getDatabaseManager(); 45 | } 46 | return null; 47 | } 48 | ], 49 | /** @see ValidationServiceProvider::registerPresenceVerifier() */ 50 | DatabasePresenceVerifierInterface::class => [ 51 | 'alias' => ['validation.presence'], 52 | 'singleton' => function () { 53 | $db = self::get(ConnectionResolverInterface::class); 54 | if (!$db instanceof ConnectionResolverInterface) { 55 | return null; 56 | } 57 | return new DatabasePresenceVerifier($db); 58 | } 59 | ], 60 | ]; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Install.php: -------------------------------------------------------------------------------- 1 | 'config/plugin/webman-tech/laravel-validation', 13 | 'copy/resource/translations/en/validation.php' => 'resource/translations/en/validation.php', 14 | 'copy/resource/translations/zh_CN/validation.php' => 'resource/translations/zh_CN/validation.php', 15 | ); 16 | 17 | /** 18 | * Install 19 | * @return void 20 | */ 21 | public static function install() 22 | { 23 | static::installByRelation(); 24 | } 25 | 26 | /** 27 | * Uninstall 28 | * @return void 29 | */ 30 | public static function uninstall() 31 | { 32 | self::uninstallByRelation(); 33 | } 34 | 35 | /** 36 | * installByRelation 37 | * @return void 38 | */ 39 | public static function installByRelation() 40 | { 41 | foreach (static::$pathRelation as $source => $dest) { 42 | if ($pos = strrpos($dest, '/')) { 43 | $parent_dir = base_path().'/'.substr($dest, 0, $pos); 44 | if (!is_dir($parent_dir)) { 45 | mkdir($parent_dir, 0777, true); 46 | } 47 | } 48 | //symlink(__DIR__ . "/$source", base_path()."/$dest"); 49 | copy_dir(__DIR__ . "/$source", base_path()."/$dest"); 50 | echo "Create $dest 51 | "; 52 | } 53 | } 54 | 55 | /** 56 | * uninstallByRelation 57 | * @return void 58 | */ 59 | public static function uninstallByRelation() 60 | { 61 | foreach (static::$pathRelation as $source => $dest) { 62 | $path = base_path()."/$dest"; 63 | if (!is_dir($path) && !is_file($path)) { 64 | continue; 65 | } 66 | echo "Remove $dest 67 | "; 68 | if (is_file($path) || is_link($path)) { 69 | unlink($path); 70 | continue; 71 | } 72 | remove_dir($path); 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /Mock/LaravelDb.php: -------------------------------------------------------------------------------- 1 | Split from [webman-tech/laravel-monorepo](https://github.com/webman-tech/laravel-monorepo) 4 | 5 | Laravel [illuminate/validation](https://packagist.org/packages/illuminate/validation) for webman 6 | 7 | ## 介绍 8 | 9 | 站在巨人(laravel)的肩膀上使验证器使用更加*可靠*和*便捷* 10 | 11 | 所有方法和配置与 laravel 几乎一模一样,因此使用方式完全参考 [Laravel文档](https://laravel.com/docs/validation) 即可 12 | 13 | ## 安装 14 | 15 | ```bash 16 | composer require webman-tech/laravel-validation 17 | ``` 18 | 19 | ## 使用 20 | 21 | 所有 API 同 laravel,以下仅对有些特殊的操作做说明 22 | 23 | 常规使用如下: 24 | 25 | ```php 26 | post(), [ 36 | 'title' => 'required|unique:posts|max:255', 37 | 'body' => 'required', 38 | ]); 39 | if ($validator->fails()) { 40 | return json($validator->errors()->first()); 41 | } 42 | return json('ok'); 43 | } 44 | } 45 | ``` 46 | 47 | ### file/mimeType 相关的 rule 48 | 49 | 由于 laravel 的 validation 验证 file/image 等文件时(包括文件 mimeType)时,都是使用的 Symfony 的 UploadedFile,而 webman 里 `$request->file()` 得到的是 `Webman\UploadFile`, 50 | 因此无法直接使用相关的 rules 51 | 52 | 需要使用 [`webman-tech/laravel-http`](https://github.com/webman-tech/laravel-http) 来支持 53 | 54 | 安装 55 | 56 | ```bash 57 | composer require webman-tech/laravel-http 58 | ``` 59 | 60 | 使用 61 | 62 | ```php 63 | 'required|file|image', 75 | ]); 76 | if ($validator->fails()) { 77 | return json($validator->errors()->first()); 78 | } 79 | return json('ok'); 80 | } 81 | } 82 | ``` 83 | 84 | ### $request->validate 85 | 86 | 需要使用 [`webman-tech/laravel-http`](https://github.com/webman-tech/laravel-http) 来支持 87 | 88 | 安装 89 | 90 | ```bash 91 | composer require webman-tech/laravel-http 92 | ``` 93 | 94 | 使用 95 | 96 | ```php 97 | 'required|file|image', 109 | ]); 110 | 111 | return json('ok'); 112 | } 113 | } 114 | ``` 115 | 116 | ### 自定义验证规则 117 | 118 | 在 `config/plugin/webman-tech/laravel-validation/app.php` 的 `extends` 字段中配置即可 119 | 120 | 配置形式同 Laravel 121 | 122 | > 目前暂未提供 make:rule 的 command,需要自己写 Rule 类 123 | 124 | ### locale 本地化翻译需求 125 | 126 | #### 支持本地化 127 | 128 | > 如果已经安装了 `symfony/translation`(webman 默认支持的),会自动使用其来支持本地化,可以忽略以下的内容 129 | 130 | 使用 [`webman-tech/laravel-translation`](https://github.com/webman-tech/laravel-translation) 来支持 131 | 132 | 安装 133 | 134 | ```bash 135 | composer require webman-tech/laravel-translation 136 | ``` 137 | 138 | #### 切换 locale 139 | 140 | 因为没有 Laravel App 的存在,所以不能通过 `App::setLocale()` 和 `App::currentLocale()` 来切换验证器的语言 141 | 142 | 且由于 webman 建议的多语言是使用的 `symfony/translation`,并且全局 `locale` 函数也是使用其实现的 143 | 144 | 因此本扩展基于此原因,已经做到了根据 `locale()` 自动切换 `validator()` 下使用的语言包,无需开发手动设置 145 | 146 | ### unique 验证器 147 | 148 | unique 依赖数据库,本扩展对已经安装 `illuminate/database` 了 webman 应用自动支持 149 | 150 | 如果不支持,比如报错:`Presence verifier has not been set.` 时,请手动安装 `illuminate/database` 151 | 152 | > 原则上不一定强依赖于 Laravel 的 database, TP 的应该也是可以的(实现 DatabasePresenceVerifierInterface),目前暂未实现,欢迎PR 153 | -------------------------------------------------------------------------------- /Translation/NullTranslator.php: -------------------------------------------------------------------------------- 1 | setLocale($locale ?: locale()); 14 | } 15 | 16 | /** 17 | * @inheritDoc 18 | */ 19 | public function get($key, array $replace = [], $locale = null) 20 | { 21 | $locale = $locale ?: $this->locale; 22 | 23 | $arr = explode('.', $key); 24 | $domain = $arr[0]; 25 | unset($arr[0]); 26 | $id = implode('.', $arr); 27 | 28 | $newReplace = []; 29 | foreach ($replace as $key => $value) { 30 | if (!in_array($key[0], ['%', ':'])) { 31 | $key = ':' . $key; 32 | } 33 | $newReplace[$key] = $value; 34 | } 35 | 36 | return trans($id, $newReplace, $domain, $locale); 37 | } 38 | 39 | /** 40 | * @inheritDoc 41 | */ 42 | public function choice($key, $number, array $replace = [], $locale = null) 43 | { 44 | $replace['%count%'] = $number; 45 | // 注意:symfony 下使用 Inf 和 -Inf 表示区间的最大值和最小值,但 laravel 下使用 * 的,此处暂时未处理 46 | return $this->get($key, $replace, $locale); 47 | } 48 | 49 | /** 50 | * @inheritDoc 51 | */ 52 | public function getLocale(): string 53 | { 54 | return $this->locale; 55 | } 56 | 57 | /** 58 | * @inheritDoc 59 | */ 60 | public function setLocale($locale): void 61 | { 62 | $this->locale = $locale; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webman-tech/laravel-validation", 3 | "type": "library", 4 | "license": "MIT", 5 | "description": "Webman plugin webman-tech/laravel-validation", 6 | "require": { 7 | "php": "^8.2", 8 | "illuminate/validation": "^12.0" 9 | }, 10 | "_comment": [ 11 | "symfony/translation for autodetct locale", 12 | "illuminate/database for unique rule" 13 | ], 14 | "autoload": { 15 | "psr-4": { 16 | "WebmanTech\\LaravelValidation\\": "" 17 | }, 18 | "files": [ 19 | "helper.php" 20 | ] 21 | }, 22 | "config": { 23 | "sort-packages": true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /copy/config/plugin/app.php: -------------------------------------------------------------------------------- 1 | true, 7 | /** 8 | * 扩展自定义验证规则 9 | */ 10 | 'extends' => function (ValidationFactory $validator): void { 11 | //$validator->extend(); 12 | } 13 | ]; 14 | -------------------------------------------------------------------------------- /copy/resource/translations/en/validation.php: -------------------------------------------------------------------------------- 1 | 'The :attribute field must be accepted.', 20 | 'accepted_if' => 'The :attribute field must be accepted when :other is :value.', 21 | 'active_url' => 'The :attribute field must be a valid URL.', 22 | 'after' => 'The :attribute field must be a date after :date.', 23 | 'after_or_equal' => 'The :attribute field must be a date after or equal to :date.', 24 | 'alpha' => 'The :attribute field must only contain letters.', 25 | 'alpha_dash' => 'The :attribute field must only contain letters, numbers, dashes, and underscores.', 26 | 'alpha_num' => 'The :attribute field must only contain letters and numbers.', 27 | 'array' => 'The :attribute field must be an array.', 28 | 'ascii' => 'The :attribute field must only contain single-byte alphanumeric characters and symbols.', 29 | 'before' => 'The :attribute field must be a date before :date.', 30 | 'before_or_equal' => 'The :attribute field must be a date before or equal to :date.', 31 | 'between' => [ 32 | 'array' => 'The :attribute field must have between :min and :max items.', 33 | 'file' => 'The :attribute field must be between :min and :max kilobytes.', 34 | 'numeric' => 'The :attribute field must be between :min and :max.', 35 | 'string' => 'The :attribute field must be between :min and :max characters.', 36 | ], 37 | 'boolean' => 'The :attribute field must be true or false.', 38 | 'can' => 'The :attribute field contains an unauthorized value.', 39 | 'confirmed' => 'The :attribute field confirmation does not match.', 40 | 'contains' => 'The :attribute field is missing a required value.', 41 | 'current_password' => 'The password is incorrect.', 42 | 'date' => 'The :attribute field must be a valid date.', 43 | 'date_equals' => 'The :attribute field must be a date equal to :date.', 44 | 'date_format' => 'The :attribute field must match the format :format.', 45 | 'decimal' => 'The :attribute field must have :decimal decimal places.', 46 | 'declined' => 'The :attribute field must be declined.', 47 | 'declined_if' => 'The :attribute field must be declined when :other is :value.', 48 | 'different' => 'The :attribute field and :other must be different.', 49 | 'digits' => 'The :attribute field must be :digits digits.', 50 | 'digits_between' => 'The :attribute field must be between :min and :max digits.', 51 | 'dimensions' => 'The :attribute field has invalid image dimensions.', 52 | 'distinct' => 'The :attribute field has a duplicate value.', 53 | 'doesnt_end_with' => 'The :attribute field must not end with one of the following: :values.', 54 | 'doesnt_start_with' => 'The :attribute field must not start with one of the following: :values.', 55 | 'email' => 'The :attribute field must be a valid email address.', 56 | 'ends_with' => 'The :attribute field must end with one of the following: :values.', 57 | 'enum' => 'The selected :attribute is invalid.', 58 | 'exists' => 'The selected :attribute is invalid.', 59 | 'extensions' => 'The :attribute field must have one of the following extensions: :values.', 60 | 'file' => 'The :attribute field must be a file.', 61 | 'filled' => 'The :attribute field must have a value.', 62 | 'gt' => [ 63 | 'array' => 'The :attribute field must have more than :value items.', 64 | 'file' => 'The :attribute field must be greater than :value kilobytes.', 65 | 'numeric' => 'The :attribute field must be greater than :value.', 66 | 'string' => 'The :attribute field must be greater than :value characters.', 67 | ], 68 | 'gte' => [ 69 | 'array' => 'The :attribute field must have :value items or more.', 70 | 'file' => 'The :attribute field must be greater than or equal to :value kilobytes.', 71 | 'numeric' => 'The :attribute field must be greater than or equal to :value.', 72 | 'string' => 'The :attribute field must be greater than or equal to :value characters.', 73 | ], 74 | 'hex_color' => 'The :attribute field must be a valid hexadecimal color.', 75 | 'image' => 'The :attribute field must be an image.', 76 | 'in' => 'The selected :attribute is invalid.', 77 | 'in_array' => 'The :attribute field must exist in :other.', 78 | 'integer' => 'The :attribute field must be an integer.', 79 | 'ip' => 'The :attribute field must be a valid IP address.', 80 | 'ipv4' => 'The :attribute field must be a valid IPv4 address.', 81 | 'ipv6' => 'The :attribute field must be a valid IPv6 address.', 82 | 'json' => 'The :attribute field must be a valid JSON string.', 83 | 'list' => 'The :attribute field must be a list.', 84 | 'lowercase' => 'The :attribute field must be lowercase.', 85 | 'lt' => [ 86 | 'array' => 'The :attribute field must have less than :value items.', 87 | 'file' => 'The :attribute field must be less than :value kilobytes.', 88 | 'numeric' => 'The :attribute field must be less than :value.', 89 | 'string' => 'The :attribute field must be less than :value characters.', 90 | ], 91 | 'lte' => [ 92 | 'array' => 'The :attribute field must not have more than :value items.', 93 | 'file' => 'The :attribute field must be less than or equal to :value kilobytes.', 94 | 'numeric' => 'The :attribute field must be less than or equal to :value.', 95 | 'string' => 'The :attribute field must be less than or equal to :value characters.', 96 | ], 97 | 'mac_address' => 'The :attribute field must be a valid MAC address.', 98 | 'max' => [ 99 | 'array' => 'The :attribute field must not have more than :max items.', 100 | 'file' => 'The :attribute field must not be greater than :max kilobytes.', 101 | 'numeric' => 'The :attribute field must not be greater than :max.', 102 | 'string' => 'The :attribute field must not be greater than :max characters.', 103 | ], 104 | 'max_digits' => 'The :attribute field must not have more than :max digits.', 105 | 'mimes' => 'The :attribute field must be a file of type: :values.', 106 | 'mimetypes' => 'The :attribute field must be a file of type: :values.', 107 | 'min' => [ 108 | 'array' => 'The :attribute field must have at least :min items.', 109 | 'file' => 'The :attribute field must be at least :min kilobytes.', 110 | 'numeric' => 'The :attribute field must be at least :min.', 111 | 'string' => 'The :attribute field must be at least :min characters.', 112 | ], 113 | 'min_digits' => 'The :attribute field must have at least :min digits.', 114 | 'missing' => 'The :attribute field must be missing.', 115 | 'missing_if' => 'The :attribute field must be missing when :other is :value.', 116 | 'missing_unless' => 'The :attribute field must be missing unless :other is :value.', 117 | 'missing_with' => 'The :attribute field must be missing when :values is present.', 118 | 'missing_with_all' => 'The :attribute field must be missing when :values are present.', 119 | 'multiple_of' => 'The :attribute field must be a multiple of :value.', 120 | 'not_in' => 'The selected :attribute is invalid.', 121 | 'not_regex' => 'The :attribute field format is invalid.', 122 | 'numeric' => 'The :attribute field must be a number.', 123 | 'password' => [ 124 | 'letters' => 'The :attribute field must contain at least one letter.', 125 | 'mixed' => 'The :attribute field must contain at least one uppercase and one lowercase letter.', 126 | 'numbers' => 'The :attribute field must contain at least one number.', 127 | 'symbols' => 'The :attribute field must contain at least one symbol.', 128 | 'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.', 129 | ], 130 | 'present' => 'The :attribute field must be present.', 131 | 'present_if' => 'The :attribute field must be present when :other is :value.', 132 | 'present_unless' => 'The :attribute field must be present unless :other is :value.', 133 | 'present_with' => 'The :attribute field must be present when :values is present.', 134 | 'present_with_all' => 'The :attribute field must be present when :values are present.', 135 | 'prohibited' => 'The :attribute field is prohibited.', 136 | 'prohibited_if' => 'The :attribute field is prohibited when :other is :value.', 137 | 'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.', 138 | 'prohibits' => 'The :attribute field prohibits :other from being present.', 139 | 'regex' => 'The :attribute field format is invalid.', 140 | 'required' => 'The :attribute field is required.', 141 | 'required_array_keys' => 'The :attribute field must contain entries for: :values.', 142 | 'required_if' => 'The :attribute field is required when :other is :value.', 143 | 'required_if_accepted' => 'The :attribute field is required when :other is accepted.', 144 | 'required_if_declined' => 'The :attribute field is required when :other is declined.', 145 | 'required_unless' => 'The :attribute field is required unless :other is in :values.', 146 | 'required_with' => 'The :attribute field is required when :values is present.', 147 | 'required_with_all' => 'The :attribute field is required when :values are present.', 148 | 'required_without' => 'The :attribute field is required when :values is not present.', 149 | 'required_without_all' => 'The :attribute field is required when none of :values are present.', 150 | 'same' => 'The :attribute field must match :other.', 151 | 'size' => [ 152 | 'array' => 'The :attribute field must contain :size items.', 153 | 'file' => 'The :attribute field must be :size kilobytes.', 154 | 'numeric' => 'The :attribute field must be :size.', 155 | 'string' => 'The :attribute field must be :size characters.', 156 | ], 157 | 'starts_with' => 'The :attribute field must start with one of the following: :values.', 158 | 'string' => 'The :attribute field must be a string.', 159 | 'timezone' => 'The :attribute field must be a valid timezone.', 160 | 'unique' => 'The :attribute has already been taken.', 161 | 'uploaded' => 'The :attribute failed to upload.', 162 | 'uppercase' => 'The :attribute field must be uppercase.', 163 | 'url' => 'The :attribute field must be a valid URL.', 164 | 'ulid' => 'The :attribute field must be a valid ULID.', 165 | 'uuid' => 'The :attribute field must be a valid UUID.', 166 | 167 | /* 168 | |-------------------------------------------------------------------------- 169 | | Custom Validation Language Lines 170 | |-------------------------------------------------------------------------- 171 | | 172 | | Here you may specify custom validation messages for attributes using the 173 | | convention "attribute.rule" to name the lines. This makes it quick to 174 | | specify a specific custom language line for a given attribute rule. 175 | | 176 | */ 177 | 178 | 'custom' => [ 179 | 'attribute-name' => [ 180 | 'rule-name' => 'custom-message', 181 | ], 182 | ], 183 | 184 | /* 185 | |-------------------------------------------------------------------------- 186 | | Custom Validation Attributes 187 | |-------------------------------------------------------------------------- 188 | | 189 | | The following language lines are used to swap our attribute placeholder 190 | | with something more reader friendly such as "E-Mail Address" instead 191 | | of "email". This simply helps us make our message more expressive. 192 | | 193 | */ 194 | 195 | 'attributes' => [], 196 | 197 | ]; 198 | -------------------------------------------------------------------------------- /copy/resource/translations/zh_CN/validation.php: -------------------------------------------------------------------------------- 1 | '您必须接受 :attribute。', 8 | 'accepted_if' => '当 :other 为 :value 时,必须接受 :attribute。', 9 | 'active_url' => ':attribute 不是一个有效的网址。', 10 | 'after' => ':attribute 必须要晚于 :date。', 11 | 'after_or_equal' => ':attribute 必须要等于 :date 或更晚。', 12 | 'alpha' => ':attribute 只能由字母组成。', 13 | 'alpha_dash' => ':attribute 只能由字母、数字、短划线(-)和下划线(_)组成。', 14 | 'alpha_num' => ':attribute 只能由字母和数字组成。', 15 | 'array' => ':attribute 必须是一个数组。', 16 | 'ascii' => ':attribute 必须仅包含单字节字母数字字符和符号。', 17 | 'before' => ':attribute 必须要早于 :date。', 18 | 'before_or_equal' => ':attribute 必须要等于 :date 或更早。', 19 | 'between' => [ 20 | 'array' => ':attribute 必须只有 :min - :max 个单元。', 21 | 'file' => ':attribute 必须介于 :min - :max KB 之间。', 22 | 'numeric' => ':attribute 必须介于 :min - :max 之间。', 23 | 'string' => ':attribute 必须介于 :min - :max 个字符之间。', 24 | ], 25 | 'boolean' => ':attribute 必须为布尔值。', 26 | 'can' => ':attribute 字段包含未经授权的值。', 27 | 'confirmed' => ':attribute 两次输入不一致。', 28 | 'contains' => ':attribute 字段缺少必填值。', 29 | 'current_password' => '密码错误。', 30 | 'date' => ':attribute 不是一个有效的日期。', 31 | 'date_equals' => ':attribute 必须要等于 :date。', 32 | 'date_format' => ':attribute 的格式必须为 :format。', 33 | 'decimal' => ':attribute 必须有 :decimal 位小数。', 34 | 'declined' => ':attribute 必须是拒绝的。', 35 | 'declined_if' => '当 :other 为 :value 时字段 :attribute 必须是拒绝的。', 36 | 'different' => ':attribute 和 :other 必须不同。', 37 | 'digits' => ':attribute 必须是 :digits 位数字。', 38 | 'digits_between' => ':attribute 必须是介于 :min 和 :max 位的数字。', 39 | 'dimensions' => ':attribute 图片尺寸不正确。', 40 | 'distinct' => ':attribute 已经存在。', 41 | 'doesnt_end_with' => ':attribute 不能以以下之一结尾: :values。', 42 | 'doesnt_start_with' => ':attribute 不能以下列之一开头: :values。', 43 | 'email' => ':attribute 不是一个合法的邮箱。', 44 | 'ends_with' => ':attribute 必须以 :values 为结尾。', 45 | 'enum' => ':attribute 值不正确。', 46 | 'exists' => ':attribute 不存在。', 47 | 'extensions' => ':attribute 字段必须具有以下扩展名之一::values。', 48 | 'file' => ':attribute 必须是文件。', 49 | 'filled' => ':attribute 不能为空。', 50 | 'gt' => [ 51 | 'array' => ':attribute 必须多于 :value 个元素。', 52 | 'file' => ':attribute 必须大于 :value KB。', 53 | 'numeric' => ':attribute 必须大于 :value。', 54 | 'string' => ':attribute 必须多于 :value 个字符。', 55 | ], 56 | 'gte' => [ 57 | 'array' => ':attribute 必须多于或等于 :value 个元素。', 58 | 'file' => ':attribute 必须大于或等于 :value KB。', 59 | 'numeric' => ':attribute 必须大于或等于 :value。', 60 | 'string' => ':attribute 必须多于或等于 :value 个字符。', 61 | ], 62 | 'hex_color' => ':attribute 字段必须是有效的十六进制颜色。', 63 | 'image' => ':attribute 必须是图片。', 64 | 'in' => '已选的属性 :attribute 无效。', 65 | 'in_array' => ':attribute 必须在 :other 中。', 66 | 'integer' => ':attribute 必须是整数。', 67 | 'ip' => ':attribute 必须是有效的 IP 地址。', 68 | 'ipv4' => ':attribute 必须是有效的 IPv4 地址。', 69 | 'ipv6' => ':attribute 必须是有效的 IPv6 地址。', 70 | 'json' => ':attribute 必须是正确的 JSON 格式。', 71 | 'list' => ':attribute 字段必须是一个列表。', 72 | 'lowercase' => ':attribute 必须小写。', 73 | 'lt' => [ 74 | 'array' => ':attribute 必须少于 :value 个元素。', 75 | 'file' => ':attribute 必须小于 :value KB。', 76 | 'numeric' => ':attribute 必须小于 :value。', 77 | 'string' => ':attribute 必须少于 :value 个字符。', 78 | ], 79 | 'lte' => [ 80 | 'array' => ':attribute 必须少于或等于 :value 个元素。', 81 | 'file' => ':attribute 必须小于或等于 :value KB。', 82 | 'numeric' => ':attribute 必须小于或等于 :value。', 83 | 'string' => ':attribute 必须少于或等于 :value 个字符。', 84 | ], 85 | 'mac_address' => ':attribute 必须是一个有效的 MAC 地址。', 86 | 'max' => [ 87 | 'array' => ':attribute 最多只有 :max 个单元。', 88 | 'file' => ':attribute 不能大于 :max KB。', 89 | 'numeric' => ':attribute 不能大于 :max。', 90 | 'string' => ':attribute 不能大于 :max 个字符。', 91 | ], 92 | 'max_digits' => ':attribute 不能超过 :max 位数。', 93 | 'mimes' => ':attribute 必须是一个 :values 类型的文件。', 94 | 'mimetypes' => ':attribute 必须是一个 :values 类型的文件。', 95 | 'min' => [ 96 | 'array' => ':attribute 至少有 :min 个单元。', 97 | 'file' => ':attribute 大小不能小于 :min KB。', 98 | 'numeric' => ':attribute 必须大于等于 :min。', 99 | 'string' => ':attribute 至少为 :min 个字符。', 100 | ], 101 | 'min_digits' => ':attribute 必须至少有 :min 位数。', 102 | 'missing' => '必须缺少 :attribute 字段。', 103 | 'missing_if' => '当 :other 为 :value 时,必须缺少 :attribute 字段。', 104 | 'missing_unless' => '必须缺少 :attribute 字段,除非 :other 是 :value。', 105 | 'missing_with' => '存在 :values 时,必须缺少 :attribute 字段。', 106 | 'missing_with_all' => '存在 :values 时,必须缺少 :attribute 字段。', 107 | 'multiple_of' => ':attribute 必须是 :value 中的多个值。', 108 | 'not_in' => '已选的属性 :attribute 非法。', 109 | 'not_regex' => ':attribute 的格式错误。', 110 | 'numeric' => ':attribute 必须是一个数字。', 111 | 'password' => [ 112 | 'letters' => ':attribute 必须至少包含一个字母。', 113 | 'mixed' => ':attribute 必须至少包含一个大写字母和一个小写字母。', 114 | 'numbers' => ':attribute 必须至少包含一个数字。', 115 | 'symbols' => ':attribute 必须至少包含一个符号。', 116 | 'uncompromised' => '给定的 :attribute 出现在已经泄漏的密码中。请选择不同的 :attribute。', 117 | ], 118 | 'present' => ':attribute 必须存在。', 119 | 'present_if' => '当 :other 等于 :value 时,必须存在 :attribute 字段。', 120 | 'present_unless' => '除非 :other 等于 :value,否则 :attribute 字段必须存在。', 121 | 'present_with' => '当 :values 存在时,:attribute 字段必须存在。', 122 | 'present_with_all' => '当存在 :values 时,必须存在 :attribute 字段。', 123 | 'prohibited' => ':attribute 字段被禁止。', 124 | 'prohibited_if' => '当 :other 为 :value 时,禁止 :attribute 字段。', 125 | 'prohibited_unless' => ':attribute 字段被禁止,除非 :other 位于 :values 中。', 126 | 'prohibits' => ':attribute 字段禁止出现 :other。', 127 | 'regex' => ':attribute 格式不正确。', 128 | 'required' => ':attribute 不能为空。', 129 | 'required_array_keys' => ':attribute 至少包含指定的键::values.', 130 | 'required_if' => '当 :other 为 :value 时 :attribute 不能为空。', 131 | 'required_if_accepted' => '当 :other 存在时,:attribute 不能为空。', 132 | 'required_if_declined' => '当 :other 不存在时,:attribute 不能为空。', 133 | 'required_unless' => '当 :other 不为 :values 时 :attribute 不能为空。', 134 | 'required_with' => '当 :values 存在时 :attribute 不能为空。', 135 | 'required_with_all' => '当 :values 存在时 :attribute 不能为空。', 136 | 'required_without' => '当 :values 不存在时 :attribute 不能为空。', 137 | 'required_without_all' => '当 :values 都不存在时 :attribute 不能为空。', 138 | 'same' => ':attribute 和 :other 必须相同。', 139 | 'size' => [ 140 | 'array' => ':attribute 必须为 :size 个单元。', 141 | 'file' => ':attribute 大小必须为 :size KB。', 142 | 'numeric' => ':attribute 大小必须为 :size。', 143 | 'string' => ':attribute 必须是 :size 个字符。', 144 | ], 145 | 'starts_with' => ':attribute 必须以 :values 为开头。', 146 | 'string' => ':attribute 必须是一个字符串。', 147 | 'timezone' => ':attribute 必须是一个合法的时区值。', 148 | 'unique' => ':attribute 已经存在。', 149 | 'uploaded' => ':attribute 上传失败。', 150 | 'uppercase' => ':attribute 必须大写', 151 | 'url' => ':attribute 格式不正确。', 152 | 'ulid' => ':attribute 必须是有效的 ULID。', 153 | 'uuid' => ':attribute 必须是有效的 UUID。', 154 | 'custom' => [ 155 | 'attribute-name' => [ 156 | 'rule-name' => 'custom-message', 157 | ], 158 | ], 159 | 'attributes' => [], 160 | ]; 161 | -------------------------------------------------------------------------------- /helper.php: -------------------------------------------------------------------------------- 1 | make($data, $rules, $messages, $customAttributes); 23 | } 24 | } 25 | --------------------------------------------------------------------------------