From e63fa665d2c6781c550157516d037c5e112c96a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 4 Nov 2020 19:04:43 +0800 Subject: [PATCH 001/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E5=92=8C=E9=83=A8=E5=88=86=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 20 +++++++++-- src/Exception/ValidateException.php | 10 ++++++ src/Support/Event/ValidateEventAbstract.php | 10 ++++++ src/Support/Event/ValidateEventInterface.php | 10 ++++++ src/Support/Event/ValidateResult.php | 10 ++++++ src/Support/Middleware/ValidateMiddleware.php | 10 ++++++ src/Support/Rule/BaseRule.php | 10 +++++- src/Support/Storage/ValidateCollection.php | 13 +++++++- src/Support/Storage/ValidateConfig.php | 10 ++++++ src/Support/Storage/ValidateHandler.php | 10 ++++++ src/Support/helpers.php | 10 ++++++ src/Validate.php | 28 +++++++++++----- tests/Material/Rules/AlphaNum.php | 17 ++++++++++ tests/Material/Rules/ChsAlphaNum.php | 25 ++++++++++++++ tests/Material/TestBaseValidate.php | 33 +++++++++++++++++++ tests/Material/TestLoginValidate.php | 33 +++++++++++++++++++ tests/TestValidate.php | 27 +++++++++++++++ 17 files changed, 273 insertions(+), 13 deletions(-) create mode 100644 tests/Material/Rules/AlphaNum.php create mode 100644 tests/Material/Rules/ChsAlphaNum.php create mode 100644 tests/Material/TestBaseValidate.php create mode 100644 tests/Material/TestLoginValidate.php create mode 100644 tests/TestValidate.php diff --git a/composer.json b/composer.json index 4b207ac..ee4dc81 100644 --- a/composer.json +++ b/composer.json @@ -1,14 +1,23 @@ { "name": "w7/engine-validate", - "require": { - "w7/rangine": "^2.3" - }, + "license": "Apache-2.0", "authors": [ { "name": "邪少", "email": "453618847@qq.com" } ], + "keywords": [ + "w7", + "validate" + ], + "require": { + "php": "^7.2|^8.0", + "w7/rangine": "^2.3" + }, + "require-dev": { + "phpunit/phpunit" : "8.5.8.*" + }, "autoload": { "psr-4": { "W7\\Validate\\" : "src/" @@ -16,5 +25,10 @@ "files": [ "src/Support/helpers.php" ] + }, + "autoload-dev": { + "psr-4": { + "W7\\Tests\\" : "tests/" + } } } \ No newline at end of file diff --git a/src/Exception/ValidateException.php b/src/Exception/ValidateException.php index 4c55699..6953926 100644 --- a/src/Exception/ValidateException.php +++ b/src/Exception/ValidateException.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate\Exception; use Exception; diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index fa15f9c..d613c4e 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate\Support\Event; use Closure; diff --git a/src/Support/Event/ValidateEventInterface.php b/src/Support/Event/ValidateEventInterface.php index 865a8cf..c12e60e 100644 --- a/src/Support/Event/ValidateEventInterface.php +++ b/src/Support/Event/ValidateEventInterface.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate\Support\Event; use Closure; diff --git a/src/Support/Event/ValidateResult.php b/src/Support/Event/ValidateResult.php index a13499b..7bf2f35 100644 --- a/src/Support/Event/ValidateResult.php +++ b/src/Support/Event/ValidateResult.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate\Support\Event; use Psr\Http\Message\RequestInterface; diff --git a/src/Support/Middleware/ValidateMiddleware.php b/src/Support/Middleware/ValidateMiddleware.php index 60fd67e..de26772 100644 --- a/src/Support/Middleware/ValidateMiddleware.php +++ b/src/Support/Middleware/ValidateMiddleware.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate\Support\Middleware; use Exception; diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index cd9a9fa..70cd187 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -1,9 +1,17 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ namespace W7\Validate\Support\Rule; - use Illuminate\Contracts\Validation\Rule; abstract class BaseRule implements Rule diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index eecbac0..1a4858b 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -1,7 +1,18 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate\Support\Storage; +use Closure; use Illuminate\Support\Arr; use Illuminate\Support\Collection; @@ -23,7 +34,7 @@ class ValidateCollection extends Collection public function get($key, $default = null) { if (false !== strpos($key, '.')) { - return Arr::get($this->items, $key, $default instanceof \Closure ? $default() : $default); + return Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); } return parent::get($key, $default); } diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 6bbc5de..cf72d8c 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate\Support\Storage; use Exception; diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index f51b006..a359e7b 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate\Support\Storage; use Psr\Http\Message\RequestInterface; diff --git a/src/Support/helpers.php b/src/Support/helpers.php index ce23dce..e322428 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + use Psr\Http\Message\ServerRequestInterface; use W7\Core\Facades\Context; use W7\Validate\Support\Storage\ValidateCollection; diff --git a/src/Validate.php b/src/Validate.php index 718e43f..4135a7d 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -1,5 +1,15 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + namespace W7\Validate; use Closure; @@ -9,6 +19,7 @@ use LogicException; use Psr\Http\Message\RequestInterface; use W7\Core\Facades\Context; use W7\Core\Facades\Validator; +use W7\Http\Message\Server\Request; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Event\ValidateResult; use W7\Validate\Support\Rule\BaseRule; @@ -74,7 +85,7 @@ class Validate */ protected $request = null; - public function __construct(RequestInterface $request = null) + public function __construct(?RequestInterface $request = null) { $this->request = $request; } @@ -113,6 +124,7 @@ class Validate private function handleEvent(array $data, string $method) { $request = $this->request ?: Context::getRequest(); + $request = $request ?: new Request('', null); $result = (new ValidateHandler($data, $this->handlers ?: [], $request))->handle($method); if (is_string($result)) { throw new ValidateException($result, 403); @@ -188,7 +200,7 @@ class Validate return $field . '.' . $rule; } - private function getScene(string $name = null) + private function getScene(?string $name = null) { $this->sometimes = []; @@ -242,7 +254,7 @@ class Validate * @param Closure|string $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator * @param string|null $message 错误消息 */ - public static function extend(string $rule, $extension, string $message = null) + public static function extend(string $rule, $extension, ?string $message = null) { array_push(self::$extendName, $rule); self::$extendName = array_unique(self::$extendName); @@ -319,7 +331,7 @@ class Validate * @param string|null $rule 验证规则 null 移除所有规则 * @return $this */ - public function remove(string $field, string $rule = null) + public function remove(string $field, ?string $rule = null) { if (isset($this->checkRule[$field])) { if (null === $rule) { @@ -403,7 +415,7 @@ class Validate * @param array|null $rules [字段 => 规则] 如果$rules为null,则清空全部验证规则 * @return $this */ - public function setRules(array $rules = null) + public function setRules(?array $rules = null) { if (null === $rules) { $this->rule = []; @@ -418,7 +430,7 @@ class Validate * @param string|null $rule 如果第一个值为字段名,则第二个值则为规则,否则请留空 * @return array|mixed|null */ - public function getMessages($key = null, string $rule = null) + public function getMessages($key = null, ?string $rule = null) { if (null === $key) { return $this->message; @@ -443,7 +455,7 @@ class Validate * @param array|null $message [字段.规则 => 验证消息] 如果$message为null,则清空全部验证消息 * @return $this */ - public function setMessages(array $message = null) + public function setMessages(?array $message = null) { if (null === $message) { $this->message = []; @@ -459,7 +471,7 @@ class Validate * @param array|null $scene [场景 => [字段]] 如果$scene为null,则清空全部验证场景 * @return $this */ - public function setScene(array $scene = null) + public function setScene(?array $scene = null) { if (null === $scene) { $this->scene = []; diff --git a/tests/Material/Rules/AlphaNum.php b/tests/Material/Rules/AlphaNum.php new file mode 100644 index 0000000..dbbb427 --- /dev/null +++ b/tests/Material/Rules/AlphaNum.php @@ -0,0 +1,17 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material\Rules; + +use W7\Validate\Support\Rule\BaseRule; + +class ChsAlphaNum extends BaseRule +{ + protected $message = ':attribute的值只能具有中文,字母,数字'; + + public function passes($attribute, $value) + { + return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u', (string)$value); + } +} diff --git a/tests/Material/TestBaseValidate.php b/tests/Material/TestBaseValidate.php new file mode 100644 index 0000000..9be4d25 --- /dev/null +++ b/tests/Material/TestBaseValidate.php @@ -0,0 +1,33 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material; + +use PHPUnit\Framework\TestCase; +use W7\Validate\Support\Storage\ValidateConfig; + +class TestBaseValidate extends TestCase +{ + public function __construct($name = null, array $data = [], $dataName = '') + { + $this->rangineInit(); + ValidateConfig::instance()->rulesPath('W7\\Tests\\Material\\Rules\\'); + + parent::__construct($name, $data, $dataName); + } + + private function rangineInit(){ + !defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 2)); + !defined('APP_PATH') && define('APP_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'app'); + !defined('RUNTIME_PATH') && define('RUNTIME_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'runtime'); + } +} diff --git a/tests/Material/TestLoginValidate.php b/tests/Material/TestLoginValidate.php new file mode 100644 index 0000000..f769fc2 --- /dev/null +++ b/tests/Material/TestLoginValidate.php @@ -0,0 +1,33 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material; + +use W7\Validate\Validate; + +class TestLoginValidate extends Validate +{ + protected $rule = [ + 'user' => 'required|chsAlphaNum', + 'pass' => 'required|alphaNum', + 'mail' => 'required|email' + ]; + + protected $message = [ + 'user.required' => '用户名必须填写', + 'user.chsAlphaNum' => '用户名的值只能具有中文,字母,数字', + 'pass.required' => '密码必须填写', + 'pass.alphaNum' => '密码的值只能具有英文字母,数字', + 'mail.required' => '邮箱必须填写', + 'mail.email' => '邮箱格式错误', + ]; +} diff --git a/tests/TestValidate.php b/tests/TestValidate.php new file mode 100644 index 0000000..7fc1add --- /dev/null +++ b/tests/TestValidate.php @@ -0,0 +1,27 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests; + +use W7\Tests\Material\TestBaseValidate; +use W7\Tests\Material\TestLoginValidate; +use W7\Validate\Exception\ValidateException; + +class TestValidate extends TestBaseValidate +{ + public function testNotScene() + { + $v = new TestLoginValidate(); + $this->expectException(ValidateException::class); + $v->check([]); + } +} -- Gitee From 33060ecb90dfa73bbd9ac24a53688ed341afd1fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 5 Nov 2020 17:10:17 +0800 Subject: [PATCH 002/152] =?UTF-8?q?[A]=20=E6=B7=BB=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 1 + tests/Material/TestArticleValidate.php | 52 +++++++++++++++++ tests/Material/TestLoginValidate.php | 33 ----------- tests/TestValidate.php | 27 --------- tests/TestValidateScene.php | 77 ++++++++++++++++++++++++++ 5 files changed, 130 insertions(+), 60 deletions(-) create mode 100644 tests/Material/TestArticleValidate.php delete mode 100644 tests/Material/TestLoginValidate.php delete mode 100644 tests/TestValidate.php create mode 100644 tests/TestValidateScene.php diff --git a/composer.json b/composer.json index ee4dc81..21ee2a7 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "name": "w7/engine-validate", + "description": "新版微擎表单验证", "license": "Apache-2.0", "authors": [ { diff --git a/tests/Material/TestArticleValidate.php b/tests/Material/TestArticleValidate.php new file mode 100644 index 0000000..4ab00ec --- /dev/null +++ b/tests/Material/TestArticleValidate.php @@ -0,0 +1,52 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material; + +use W7\Validate\Validate; + +class TestArticleValidate extends Validate +{ + protected $rule = [ + 'id' => 'required|numeric', + 'content' => 'required|between:1,2000', + 'title' => 'required|between:4,50|alpha', + 'type' => 'required|numeric', + ]; + + protected $message = [ + 'id.required' => '缺少参数:文章Id', + 'id.numeric' => '参数错误:文章Id', + 'content.required' => '文章内容必须填写', + 'content.digits_between' => '文章长度为1~2000个字符', + 'title.required' => '文章标题必须填写', + 'title.digits_between' => '文章标题格式错误', + 'title.alpha' => '文章标题长度为4~50个字符', + 'type.required' => '文章分类必须填写', + 'type.numeric' => '文章分类错误', + ]; + + protected $scene = [ + 'add' => ['content','title'], + 'save' => ['use' => 'edit'], + 'del' => ['id'], + ]; + + public function sceneEdit() + { + return $this->only(['id','content','title']) + ->append('id', 'max:10000') + ->remove('content', 'between') + ->remove('title', null) + ->append('title', 'required|between:4,50|alpha'); + } +} diff --git a/tests/Material/TestLoginValidate.php b/tests/Material/TestLoginValidate.php deleted file mode 100644 index f769fc2..0000000 --- a/tests/Material/TestLoginValidate.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Tests\Material; - -use W7\Validate\Validate; - -class TestLoginValidate extends Validate -{ - protected $rule = [ - 'user' => 'required|chsAlphaNum', - 'pass' => 'required|alphaNum', - 'mail' => 'required|email' - ]; - - protected $message = [ - 'user.required' => '用户名必须填写', - 'user.chsAlphaNum' => '用户名的值只能具有中文,字母,数字', - 'pass.required' => '密码必须填写', - 'pass.alphaNum' => '密码的值只能具有英文字母,数字', - 'mail.required' => '邮箱必须填写', - 'mail.email' => '邮箱格式错误', - ]; -} diff --git a/tests/TestValidate.php b/tests/TestValidate.php deleted file mode 100644 index 7fc1add..0000000 --- a/tests/TestValidate.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Tests; - -use W7\Tests\Material\TestBaseValidate; -use W7\Tests\Material\TestLoginValidate; -use W7\Validate\Exception\ValidateException; - -class TestValidate extends TestBaseValidate -{ - public function testNotScene() - { - $v = new TestLoginValidate(); - $this->expectException(ValidateException::class); - $v->check([]); - } -} diff --git a/tests/TestValidateScene.php b/tests/TestValidateScene.php new file mode 100644 index 0000000..05b7400 --- /dev/null +++ b/tests/TestValidateScene.php @@ -0,0 +1,77 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests; + +use W7\Tests\Material\TestArticleValidate; +use W7\Tests\Material\TestBaseValidate; +use W7\Validate\Exception\ValidateException; + +class TestValidateScene extends TestBaseValidate +{ + /** @var array */ + protected $userInput; + public function __construct($name = null, array $data = [], $dataName = '') + { + parent::__construct($name, $data, $dataName); + $this->userInput = [ + 'content' => '内容', + 'title' => '这是一个标题' + ]; + + } + + /** + * @test 测试没有指定验证场景的情况 + * @throws ValidateException + */ + public function testNotScene() + { + $v = new TestArticleValidate(); + $this->expectException(ValidateException::class); + $v->check($this->userInput); + } + + /** + * @test 测试制定验证场景 + * @throws ValidateException + */ + public function testScene() + { + $v = new TestArticleValidate(); + $data = $v->scene('add')->check($this->userInput); + $this->assertEquals("内容",$data['content']); + } + + /** + * @test 测试自定义验证场景 edit + * @throws ValidateException + */ + public function testCustomScene() + { + + $validate = new TestArticleValidate(); + $this->expectException(ValidateException::class); + $validate->scene('edit')->check($this->userInput); + } + + /** + * @test 测试Use自定义验证场景 save + * @throws ValidateException + */ + public function testUseScene() + { + $validate = new TestArticleValidate(); + $this->expectExceptionMessage("缺少参数:文章Id"); + $validate->scene('save')->check($this->userInput); + } +} \ No newline at end of file -- Gitee From d6996727dfed73512fc471033febada7c45de504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 9 Nov 2020 15:26:32 +0800 Subject: [PATCH 003/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=9C=BA=E6=99=AFRemove=E9=9C=80=E8=A6=81=E5=A1=AB?= =?UTF-8?q?=E5=85=A5=E5=AE=8C=E6=95=B4=E8=A7=84=E5=88=99=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20[A]=20=E5=A2=9E=E5=8A=A0=E5=AF=B9=E5=BA=94=E7=9A=84?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 13 +++++- tests/Material/TestArticleValidate.php | 6 +++ tests/TestValidateScene.php | 60 +++++++++++++++----------- 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 4135a7d..e393ac5 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -341,8 +341,17 @@ class Validate if (!is_array($rules)) { $rules = explode('|', $rules); } - $rules = collect($rules); - $this->checkRule[$field] = $rules->diff(explode('|', $rule)); + $rules = collect($rules); + if (false !== strpos($rule, ':')) { + $rule = substr($rule, 0, strpos($rule, ':')); + } + $rules = $rules->filter(function ($value) use ($rule) { + if (false !== strpos($value, ':')) { + $value = substr($value, 0, strpos($value, ':')); + } + return $value !== $rule; + }); + $this->checkRule[$field] = $rules; } } return $this; diff --git a/tests/Material/TestArticleValidate.php b/tests/Material/TestArticleValidate.php index 4ab00ec..6cc590d 100644 --- a/tests/Material/TestArticleValidate.php +++ b/tests/Material/TestArticleValidate.php @@ -49,4 +49,10 @@ class TestArticleValidate extends Validate ->remove('title', null) ->append('title', 'required|between:4,50|alpha'); } + + public function sceneDynamic() + { + return $this->only(['title','content']) + ->remove('content', 'between'); + } } diff --git a/tests/TestValidateScene.php b/tests/TestValidateScene.php index 05b7400..d7b4d32 100644 --- a/tests/TestValidateScene.php +++ b/tests/TestValidateScene.php @@ -18,38 +18,37 @@ use W7\Validate\Exception\ValidateException; class TestValidateScene extends TestBaseValidate { - /** @var array */ - protected $userInput; - public function __construct($name = null, array $data = [], $dataName = '') - { - parent::__construct($name, $data, $dataName); - $this->userInput = [ - 'content' => '内容', - 'title' => '这是一个标题' - ]; - - } + /** @var array */ + protected $userInput; + public function __construct($name = null, array $data = [], $dataName = '') + { + parent::__construct($name, $data, $dataName); + $this->userInput = [ + 'content' => '内容', + 'title' => '这是一个标题' + ]; + } - /** - * @test 测试没有指定验证场景的情况 - * @throws ValidateException - */ - public function testNotScene() + /** + * @test 测试没有指定验证场景的情况 + * @throws ValidateException + */ + public function testNotScene() { $v = new TestArticleValidate(); $this->expectException(ValidateException::class); $v->check($this->userInput); } - /** - * @test 测试制定验证场景 - * @throws ValidateException - */ + /** + * @test 测试制定验证场景 + * @throws ValidateException + */ public function testScene() { - $v = new TestArticleValidate(); - $data = $v->scene('add')->check($this->userInput); - $this->assertEquals("内容",$data['content']); + $v = new TestArticleValidate(); + $data = $v->scene('add')->check($this->userInput); + $this->assertEquals('内容', $data['content']); } /** @@ -58,7 +57,6 @@ class TestValidateScene extends TestBaseValidate */ public function testCustomScene() { - $validate = new TestArticleValidate(); $this->expectException(ValidateException::class); $validate->scene('edit')->check($this->userInput); @@ -71,7 +69,17 @@ class TestValidateScene extends TestBaseValidate public function testUseScene() { $validate = new TestArticleValidate(); - $this->expectExceptionMessage("缺少参数:文章Id"); + $this->expectExceptionMessage('缺少参数:文章Id'); $validate->scene('save')->check($this->userInput); } -} \ No newline at end of file + + public function testDynamicScene() + { + $validate = new TestArticleValidate(); + $data = $validate->scene('dynamic')->check([ + 'title' => '标题标题标题标题', + 'content' => '1' + ]); + $this->assertEquals('1', $data['content']); + } +} -- Gitee From 7beddacf42f662097a47f12e75b28a68594e30ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 13 Nov 2020 13:55:22 +0800 Subject: [PATCH 004/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=9C=BA=E6=99=AF=E4=B8=ADremove=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=B8=AA=E8=A7=84=E5=88=99=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 4 ++-- src/Validate.php | 47 +++++++++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/composer.json b/composer.json index 21ee2a7..818d85c 100644 --- a/composer.json +++ b/composer.json @@ -4,8 +4,8 @@ "license": "Apache-2.0", "authors": [ { - "name": "邪少", - "email": "453618847@qq.com" + "name": "虞灪", + "email": "995645888@qq.com" } ], "keywords": [ diff --git a/src/Validate.php b/src/Validate.php index e393ac5..eadc155 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -333,27 +333,38 @@ class Validate */ public function remove(string $field, ?string $rule = null) { - if (isset($this->checkRule[$field])) { - if (null === $rule) { - unset($this->checkRule[$field]); - } else { - $rules = $this->checkRule[$field]; - if (!is_array($rules)) { - $rules = explode('|', $rules); - } - $rules = collect($rules); - if (false !== strpos($rule, ':')) { - $rule = substr($rule, 0, strpos($rule, ':')); - } - $rules = $rules->filter(function ($value) use ($rule) { - if (false !== strpos($value, ':')) { - $value = substr($value, 0, strpos($value, ':')); + $removeRule = $rule; + if (!is_array($rule) && false !== strpos($rule, '|')) { + $removeRule = explode('|', $rule); + } + if (is_array($removeRule)) { + foreach ($removeRule as $rule) { + $this->remove($field, $rule); + } + } else { + if (isset($this->checkRule[$field])) { + if (null === $rule) { + unset($this->checkRule[$field]); + } else { + $rules = $this->checkRule[$field]; + if (!is_array($rules)) { + $rules = explode('|', $rules); + } + $rules = collect($rules); + if (false !== strpos($rule, ':')) { + $rule = substr($rule, 0, strpos($rule, ':')); } - return $value !== $rule; - }); - $this->checkRule[$field] = $rules; + $rules = $rules->filter(function ($value) use ($rule) { + if (false !== strpos($value, ':')) { + $value = substr($value, 0, strpos($value, ':')); + } + return $value !== $rule; + })->toArray(); + $this->checkRule[$field] = $rules; + } } } + return $this; } -- Gitee From 4a7c811704d496ca290db900ef27c84ac03eea3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 13 Nov 2020 19:02:26 +0800 Subject: [PATCH 005/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DRemove=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E7=9A=84=E6=97=B6=E5=80=99=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20[U]=20sometimes=E6=94=AF=E6=8C=81=E5=8A=A8=E6=80=81=E8=A7=84?= =?UTF-8?q?=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 102 +++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 56 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index eadc155..415a5f5 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -14,6 +14,7 @@ namespace W7\Validate; use Closure; use Illuminate\Support\Collection; +use Illuminate\Support\Fluent; use Illuminate\Validation\ValidationException; use LogicException; use Psr\Http\Message\RequestInterface; @@ -61,12 +62,6 @@ class Validate */ private $checkRule; - /** - * sometimes验证 - * @var array - */ - private $sometimes = []; - /** * 扩展方法名 * @var array @@ -78,18 +73,24 @@ class Validate * @var array */ private $handlers = []; - + /** * Request请求实例 * @var RequestInterface|null */ protected $request = null; - + + /** + * 当前进行验证的数据 + * @var array + */ + protected $checkData = []; + public function __construct(?RequestInterface $request = null) { $this->request = $request; } - + /** * 自动验证 * @param array $data @@ -99,14 +100,10 @@ class Validate public function check(array $data) { try { - $data = $this->handleEvent($data, 'beforeValidate'); + $this->checkData = $data; + $data = $this->handleEvent($data, 'beforeValidate'); /** @var \Illuminate\Validation\Validator $v */ - $v = Validator::make($data, $this->getSceneRules(), $this->message, $this->customAttributes); - if (!empty($this->sometimes)) { - foreach ($this->sometimes as $sometime) { - $v->sometimes(...$sometime); - } - } + $v = Validator::make($data, $this->getSceneRules(), $this->message, $this->customAttributes); $data = $this->handleEvent($v->validate(), 'afterValidate'); return $data; } catch (ValidationException $e) { @@ -132,10 +129,10 @@ class Validate $this->request = $result->getRequest(); return $result->getData(); } - + throw new LogicException('Validate event return type error'); } - + public function getRequest() { return $this->request; @@ -202,8 +199,6 @@ class Validate private function getScene(?string $name = null) { - $this->sometimes = []; - if (empty($name)) { $this->checkRule = collect($this->rule); return $this; @@ -246,7 +241,7 @@ class Validate } return false; } - + /** * 注册自定义验证方法 * @@ -276,7 +271,7 @@ class Validate $this->currentScene = $name; return $this; } - + /** * @param string $handler * @param mixed ...$params @@ -310,11 +305,12 @@ class Validate public function append(string $field, string $rule) { if (isset($this->checkRule[$field])) { + if (is_array($this->checkRule[$field])) { + $this->checkRule[$field] = collect($this->checkRule[$field]); + } + if ($this->checkRule[$field] instanceof Collection) { - $appendRule = $rule; - if (!is_array($appendRule)) { - $appendRule = explode('|', $appendRule); - } + $appendRule = explode('|', $rule); $this->checkRule[$field] = $this->checkRule[$field]->concat($appendRule); } else { $this->checkRule[$field] = $this->checkRule[$field] . '|' . $rule; @@ -334,9 +330,10 @@ class Validate public function remove(string $field, ?string $rule = null) { $removeRule = $rule; - if (!is_array($rule) && false !== strpos($rule, '|')) { + if (is_string($rule) && false !== strpos($rule, '|')) { $removeRule = explode('|', $rule); } + if (is_array($removeRule)) { foreach ($removeRule as $rule) { $this->remove($field, $rule); @@ -347,10 +344,11 @@ class Validate unset($this->checkRule[$field]); } else { $rules = $this->checkRule[$field]; - if (!is_array($rules)) { + if (is_string($rules)) { $rules = explode('|', $rules); + $rules = collect($rules); } - $rules = collect($rules); + if (false !== strpos($rule, ':')) { $rule = substr($rule, 0, strpos($rule, ':')); } @@ -359,7 +357,8 @@ class Validate $value = substr($value, 0, strpos($value, ':')); } return $value !== $rule; - })->toArray(); + }); + $this->checkRule[$field] = $rules; } } @@ -373,40 +372,31 @@ class Validate * * @param string|string[] $attribute 字段 * @param string|array|BaseRule $rules 规则 - * @param callable $callback 回调方法,返回true规则生效 + * @param callable $callback 回调方法,返回true获取具体规则生效 * @return $this */ public function sometimes($attribute, $rules, callable $callback) { - if (is_string($rules)) { - $rules = collect(explode('|', $rules)); - } elseif (is_array($rules)) { - $rules = collect($rules); + $data = new Fluent($this->checkData); + $result = $callback($data); + if (false === $result) { + return $this; + } elseif (true === $result) { + $result = $rules; } - if ($rules instanceof Collection) { - $rules->transform(function ($rule) use ($attribute) { - if (is_string($rule)) { - $ruleClass = $this->getRuleClass($rule); - if (false !== $ruleClass) { - if (is_array($attribute) && !empty($attribute)) { - $attr = $attribute[0]; - } else { - $attr = $attribute; - } - $message = $this->getMessages($attr, $rule); - if (false !== $message) { - $ruleClass->setMessage($message); - } - return $ruleClass; - } - } - return $rule; - }); - $rules = $rules->toArray(); + if (is_array($result)) { + $result = implode('|', $result); + } + + if (is_array($attribute)) { + foreach ($attribute as $filed) { + $this->append($filed, $result); + } + } else { + $this->append($attribute, $result); } - $this->sometimes[] = [$attribute,$rules,$callback]; return $this; } -- Gitee From 26b893ada35f95c499dbade7e8a7a224ac9ed4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 16 Nov 2020 15:11:12 +0800 Subject: [PATCH 006/152] =?UTF-8?q?[A]=20=E5=9C=BA=E6=99=AF=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=94=AF=E6=8C=81=E5=A4=9A=E4=B8=AA=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 82 +++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 415a5f5..8dc5224 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -197,41 +197,53 @@ class Validate return $field . '.' . $rule; } - private function getScene(?string $name = null) - { - if (empty($name)) { - $this->checkRule = collect($this->rule); - return $this; - } - # 判断自定义验证场景是否存在 - if (method_exists($this, 'scene' . ucfirst($name))) { - $this->checkRule = collect($this->rule); - call_user_func([$this, 'scene' . ucfirst($name)]); - } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 - $sceneRule = $this->scene[$name]; - if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { // 判断验证场景是否指定了其他验证场景 - $this->getScene($sceneRule['use']); - } else { - $this->checkRule = collect($this->rule)->only($sceneRule); - } - - # 判断是否定义了事件 - if (isset($sceneRule['handler'])) { - $handler = $sceneRule['handler']; - if (is_string($handler)) { - $this->handlers[] = [$handler,[]]; - } else { - $handlerClass = array_shift($handler); - $this->handler($handlerClass, ...$handler); - } - } - } else { - # 如果验证场景找不到,则默认验证全部规则 - $this->checkRule = collect($this->rule); - } - - return $this; - } + private function getScene(?string $name = null) + { + if (empty($name)) { + $this->checkRule = collect($this->rule); + return $this; + } + # 判断自定义验证场景是否存在 + if (method_exists($this, 'scene' . ucfirst($name))) { + $this->checkRule = collect($this->rule); + call_user_func([$this, 'scene' . ucfirst($name)]); + } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 + $sceneRule = $this->scene[$name]; + + # 判断是否定义了事件 + if (isset($sceneRule['handler'])) { + $handlers = $sceneRule['handler']; + if (is_string($handlers)) { + $this->handlers[] = [$handlers,[]]; + } else { + foreach ($handlers as $handlerClass => $param) { + if (is_int($handlerClass)) { + $this->handlers[] = [$param,[]]; + } elseif (is_string($handlerClass)) { + if (is_array($param)){ + $this->handler($handlerClass, ...$param); + }else{ + $this->handler($handlerClass, $param); + } + } + } + } + unset($sceneRule['handler']); + } + + if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { // 判断验证场景是否指定了其他验证场景 + $this->getScene($sceneRule['use']); + unset($sceneRule['use']); + } else { + $this->checkRule = collect($this->rule)->only($sceneRule); + } + } else { + # 如果验证场景找不到,则默认验证全部规则 + $this->checkRule = collect($this->rule); + } + + return $this; + } private function getRuleClass(string $ruleName) { -- Gitee From 21efd8d511261877bd6ba1b7f874e21bf20e9f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 16 Nov 2020 15:46:13 +0800 Subject: [PATCH 007/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E4=BA=8B=E4=BB=B6=E5=A4=84=E7=90=86=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 108 ++++++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 8dc5224..f3de986 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -47,6 +47,12 @@ class Validate */ protected $scene = []; + /** + * 全局事件处理器 + * @var array + */ + protected $handler = []; + /** @var array */ protected $customAttributes = []; @@ -122,7 +128,8 @@ class Validate { $request = $this->request ?: Context::getRequest(); $request = $request ?: new Request('', null); - $result = (new ValidateHandler($data, $this->handlers ?: [], $request))->handle($method); + $this->addHandler($this->handler); + $result = (new ValidateHandler($data, $this->handlers, $request))->handle($method); if (is_string($result)) { throw new ValidateException($result, 403); } elseif ($result instanceof ValidateResult) { @@ -197,53 +204,58 @@ class Validate return $field . '.' . $rule; } - private function getScene(?string $name = null) - { - if (empty($name)) { - $this->checkRule = collect($this->rule); - return $this; - } - # 判断自定义验证场景是否存在 - if (method_exists($this, 'scene' . ucfirst($name))) { - $this->checkRule = collect($this->rule); - call_user_func([$this, 'scene' . ucfirst($name)]); - } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 - $sceneRule = $this->scene[$name]; - - # 判断是否定义了事件 - if (isset($sceneRule['handler'])) { - $handlers = $sceneRule['handler']; - if (is_string($handlers)) { - $this->handlers[] = [$handlers,[]]; - } else { - foreach ($handlers as $handlerClass => $param) { - if (is_int($handlerClass)) { - $this->handlers[] = [$param,[]]; - } elseif (is_string($handlerClass)) { - if (is_array($param)){ - $this->handler($handlerClass, ...$param); - }else{ - $this->handler($handlerClass, $param); - } - } - } - } - unset($sceneRule['handler']); - } - - if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { // 判断验证场景是否指定了其他验证场景 - $this->getScene($sceneRule['use']); - unset($sceneRule['use']); - } else { - $this->checkRule = collect($this->rule)->only($sceneRule); - } - } else { - # 如果验证场景找不到,则默认验证全部规则 - $this->checkRule = collect($this->rule); - } - - return $this; - } + private function addHandler($handlers) + { + if (is_string($handlers)) { + $this->handlers[] = [$handlers,[]]; + } else { + foreach ($handlers as $handlerClass => $param) { + if (is_int($handlerClass)) { + $this->handlers[] = [$param,[]]; + } elseif (is_string($handlerClass)) { + if (is_array($param)) { + $this->handler($handlerClass, ...$param); + } else { + $this->handler($handlerClass, $param); + } + } + } + } + } + + private function getScene(?string $name = null) + { + if (empty($name)) { + $this->checkRule = collect($this->rule); + return $this; + } + # 判断自定义验证场景是否存在 + if (method_exists($this, 'scene' . ucfirst($name))) { + $this->checkRule = collect($this->rule); + call_user_func([$this, 'scene' . ucfirst($name)]); + } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 + $sceneRule = $this->scene[$name]; + + # 判断是否定义了事件 + if (isset($sceneRule['handler'])) { + $handlers = $sceneRule['handler']; + $this->addHandler($handlers); + unset($sceneRule['handler']); + } + + if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { // 判断验证场景是否指定了其他验证场景 + $this->getScene($sceneRule['use']); + unset($sceneRule['use']); + } else { + $this->checkRule = collect($this->rule)->only($sceneRule); + } + } else { + # 如果验证场景找不到,则默认验证全部规则 + $this->checkRule = collect($this->rule); + } + + return $this; + } private function getRuleClass(string $ruleName) { -- Gitee From dc999bbc7c0ea9d2ba8ee559e065de7c6e54d3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 18 Nov 2020 11:35:36 +0800 Subject: [PATCH 008/152] =?UTF-8?q?[A]=20=E5=9C=BA=E6=99=AF=E5=AE=9A?= =?UTF-8?q?=E4=B9=89use=E5=85=B3=E9=94=AE=E8=AF=8D=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E9=97=AD=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index f3de986..981321c 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -243,9 +243,17 @@ class Validate unset($sceneRule['handler']); } - if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { // 判断验证场景是否指定了其他验证场景 - $this->getScene($sceneRule['use']); - unset($sceneRule['use']); + # 判断验证场景是否指定了其他验证场景 + if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { + $use = $sceneRule['use']; + if (method_exists($this, 'use' . ucfirst($use))) { + $use = call_user_func([$this,'use' . ucfirst($use)], $this->checkData); + if (is_array($use)) { + $this->checkRule = collect($this->rule)->only($use); + return $this; + } + } + $this->getScene($use); } else { $this->checkRule = collect($this->rule)->only($sceneRule); } -- Gitee From 5102459c9bfcf89492ce7e3073459dec8c10d6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 18 Nov 2020 13:44:46 +0800 Subject: [PATCH 009/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E5=9C=A8?= =?UTF-8?q?=E6=9C=89use=E5=85=B3=E9=94=AE=E8=AF=8D=E7=9A=84=E5=90=8C?= =?UTF-8?q?=E6=97=B6=E4=B9=9F=E5=8F=AF=E4=BB=A5=E5=88=A4=E6=96=AD=E5=85=B6?= =?UTF-8?q?=E4=BB=96=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 981321c..64ca01b 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -233,7 +233,7 @@ class Validate if (method_exists($this, 'scene' . ucfirst($name))) { $this->checkRule = collect($this->rule); call_user_func([$this, 'scene' . ucfirst($name)]); - } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 + } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 $sceneRule = $this->scene[$name]; # 判断是否定义了事件 @@ -246,8 +246,12 @@ class Validate # 判断验证场景是否指定了其他验证场景 if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { $use = $sceneRule['use']; + unset($this->scene[$name]['use']); if (method_exists($this, 'use' . ucfirst($use))) { - $use = call_user_func([$this,'use' . ucfirst($use)], $this->checkData); + /** @var \Illuminate\Validation\Validator $v */ + $v = Validator::make($this->checkData, $this->getSceneRules(), $this->message, $this->customAttributes); + $data = $v->validate(); + $use = call_user_func([$this,'use' . ucfirst($use)], $data); if (is_array($use)) { $this->checkRule = collect($this->rule)->only($use); return $this; -- Gitee From 987789a48834f545363132f933e0d3246514dc82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 18 Nov 2020 16:26:27 +0800 Subject: [PATCH 010/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D`beforeValidate?= =?UTF-8?q?`=E4=BA=8B=E4=BB=B6=E4=B8=8D=E7=94=9F=E6=95=88=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 64ca01b..350a47d 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -107,9 +107,10 @@ class Validate { try { $this->checkData = $data; + $rule = $this->getSceneRules(); $data = $this->handleEvent($data, 'beforeValidate'); /** @var \Illuminate\Validation\Validator $v */ - $v = Validator::make($data, $this->getSceneRules(), $this->message, $this->customAttributes); + $v = Validator::make($data, $rule, $this->message, $this->customAttributes); $data = $this->handleEvent($v->validate(), 'afterValidate'); return $data; } catch (ValidationException $e) { @@ -241,17 +242,26 @@ class Validate $handlers = $sceneRule['handler']; $this->addHandler($handlers); unset($sceneRule['handler']); + unset($this->scene[$name]['handler']); } # 判断验证场景是否指定了其他验证场景 if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { $use = $sceneRule['use']; + unset($sceneRule['use']); unset($this->scene[$name]['use']); + # 如果指定的use是一个方法 if (method_exists($this, 'use' . ucfirst($use))) { - /** @var \Illuminate\Validation\Validator $v */ - $v = Validator::make($this->checkData, $this->getSceneRules(), $this->message, $this->customAttributes); - $data = $v->validate(); - $use = call_user_func([$this,'use' . ucfirst($use)], $data); + # 进行预验证,将需要传给闭包的值按指定规则进行验证 + $data = []; + if (!empty($sceneRule)) { + $randScene = md5(rand(1, 1000000) . time()); + $data = (clone $this)->setScene( + [$randScene => $sceneRule] + )->scene($randScene)->check($this->checkData); + } + + $use = call_user_func([$this,'use' . ucfirst($use)], $data); if (is_array($use)) { $this->checkRule = collect($this->rule)->only($use); return $this; -- Gitee From f94d885c7dba058cde046e541b924494a808f2ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 23 Nov 2020 19:08:24 +0800 Subject: [PATCH 011/152] =?UTF-8?q?[A]=20Event=E5=A2=9E=E5=8A=A0=E5=8F=82?= =?UTF-8?q?=E6=95=B0=20[F]=20=E4=BF=AE=E5=A4=8Dhandler=E4=BC=9A=E5=A4=84?= =?UTF-8?q?=E7=90=86=E4=B8=A4=E6=AC=A1=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Event/ValidateEventAbstract.php | 36 +++++++++++++++++++++ src/Support/Storage/ValidateHandler.php | 33 +++++++++++++++---- src/Validate.php | 4 +-- 3 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index d613c4e..556b42a 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -17,6 +17,24 @@ use Psr\Http\Message\ServerRequestInterface; abstract class ValidateEventAbstract implements ValidateEventInterface { + /** + * 当前验证场景 + * @var string + */ + protected $sceneName; + + /** + * 当前控制器名称 + * @var string + */ + protected $controller; + + /** + * 当前操作方法 + * @var string + */ + protected $method; + /** * 场景验证前 * @param array $data 用户输入的数据 @@ -40,4 +58,22 @@ abstract class ValidateEventAbstract implements ValidateEventInterface { return $next($data, $request); } + + final public function setSceneName(?string $sceneName) + { + $this->sceneName = $sceneName; + return $this; + } + + final public function setController(string $controller) + { + $this->controller = $controller; + return $this; + } + + final public function setMethod(string $method) + { + $this->method = $method; + return $this; + } } diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index a359e7b..d877565 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -27,12 +27,26 @@ class ValidateHandler /** @var RequestInterface */ protected $request; - - public function __construct(array $data, array $handlers, RequestInterface $request) + + /** @var string */ + protected $sceneName = null; + + /** @var string */ + protected $controller; + + /** @var string */ + protected $method; + + public function __construct(array $data, array $handlers, RequestInterface $request, string $sceneName = null) { - $this->data = $data; - $this->request = $request; - $this->handlers = $handlers; + $this->data = $data; + $this->request = $request; + $this->handlers = $handlers; + $this->sceneName = $sceneName; + + $route = $request->getAttribute('route'); + $this->controller = $route['controller'] ?? ''; + $this->method = $route['method'] ?? ''; } protected function carry() @@ -47,10 +61,15 @@ class ValidateHandler protected function pipes(string $method) { return array_map(function ($middleware) use ($method) { - return function ($data, $request, $next) use ($middleware,$method) { + return function ($data, $request, $next) use ($middleware, $method) { list($callback, $param) = $middleware; if (class_exists($callback) && is_subclass_of($callback, ValidateEventAbstract::class)) { - return call_user_func([new $callback(...$param), $method], $data, $request, $next); + /** @var ValidateEventAbstract $handler */ + $handler = new $callback(...$param); + $handler->setSceneName($this->sceneName) + ->setController($this->controller) + ->setMethod($this->method); + return call_user_func([$handler, $method], $data, $request, $next); } else { throw new ValidateException('Event error or nonexistence'); } diff --git a/src/Validate.php b/src/Validate.php index 350a47d..9946766 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -129,8 +129,7 @@ class Validate { $request = $this->request ?: Context::getRequest(); $request = $request ?: new Request('', null); - $this->addHandler($this->handler); - $result = (new ValidateHandler($data, $this->handlers, $request))->handle($method); + $result = (new ValidateHandler($data, $this->handlers, $request, $this->currentScene))->handle($method); if (is_string($result)) { throw new ValidateException($result, 403); } elseif ($result instanceof ValidateResult) { @@ -155,6 +154,7 @@ class Validate private function getSceneRules() { $this->init(); + $this->addHandler($this->handler); $this->getScene($this->currentScene); $this->checkRule->transform(function ($rule, $field) { if (!is_array($rule) && !$rule instanceof Collection) { -- Gitee From 86c16568cb1f0904558c112677fac3ed8eeb89f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 2 Dec 2020 11:19:01 +0800 Subject: [PATCH 012/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8Dremove=E8=A7=84?= =?UTF-8?q?=E5=88=99=E4=B8=BAnull=E6=97=B6=EF=BC=8C=E5=86=8Dappend?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=A7=84=E5=88=99=E9=80=A0=E6=88=90=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Validate.php b/src/Validate.php index 9946766..844eba9 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -387,7 +387,7 @@ class Validate } else { if (isset($this->checkRule[$field])) { if (null === $rule) { - unset($this->checkRule[$field]); + $this->checkRule[$field] = []; } else { $rules = $this->checkRule[$field]; if (is_string($rules)) { -- Gitee From 99c959625018a51aaa3fed075d1ee89efec36c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 2 Dec 2020 16:03:11 +0800 Subject: [PATCH 013/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0whenHas?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A6=82=E6=9E=9C=E6=8C=87=E5=AE=9A?= =?UTF-8?q?Key=E5=AD=98=E5=9C=A8=E5=88=99=E6=89=A7=E8=A1=8C=E5=9B=9E?= =?UTF-8?q?=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 1a4858b..6cd2501 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -30,7 +30,12 @@ class ValidateCollection extends Collection return true; } - + + public function whenHas($key, Closure $closure) + { + return $this->when($this->has($key), $closure); + } + public function get($key, $default = null) { if (false !== strpos($key, '.')) { -- Gitee From d8d3f20dc809f8f7a308009dc4ca11fd8f8d28a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 3 Dec 2020 10:15:09 +0800 Subject: [PATCH 014/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0whenNotHas?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 6cd2501..4a376b8 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -36,6 +36,11 @@ class ValidateCollection extends Collection return $this->when($this->has($key), $closure); } + public function whenNotHas($key, Closure $closure) + { + return $this->when(!$this->has($key), $closure); + } + public function get($key, $default = null) { if (false !== strpos($key, '.')) { -- Gitee From aa4e493de2042b49cff75c168640f5358d354fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 3 Dec 2020 11:19:35 +0800 Subject: [PATCH 015/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9whenHas?= =?UTF-8?q?=E5=92=8CwhenNotHas=E7=9A=84=E5=8F=82=E6=95=B0=E4=B8=BAcallable?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=EF=BC=8C=E5=B9=B6=E5=A2=9E=E5=8A=A0default?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 4a376b8..136cc50 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -31,14 +31,14 @@ class ValidateCollection extends Collection return true; } - public function whenHas($key, Closure $closure) + public function whenHas($key, callable $callback, callable $default = null) { - return $this->when($this->has($key), $closure); + return $this->when($this->has($key), $callback, $default); } - public function whenNotHas($key, Closure $closure) + public function whenNotHas($key, callable $callback, callable $default = null) { - return $this->when(!$this->has($key), $closure); + return $this->when(!$this->has($key), $callback, $default); } public function get($key, $default = null) -- Gitee From 8a9780de7c0165a81d815610710ad03a0fb3a4c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 8 Dec 2020 18:18:29 +0800 Subject: [PATCH 016/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=BF=94=E5=9B=9E=E7=B1=BB=E5=9E=8B=20[A]=20=E6=8C=87?= =?UTF-8?q?=E5=AE=9A=E9=AA=8C=E8=AF=81=E5=99=A8=E5=85=B3=E8=81=94=E8=A7=84?= =?UTF-8?q?=E5=88=99=20[U]=20=E6=94=AF=E6=8C=81=E5=A4=9A=E4=B8=AA=E8=B7=AF?= =?UTF-8?q?=E5=BE=84=E6=98=A0=E5=B0=84=20[U]=20=E6=94=AF=E6=8C=81=E5=A4=9A?= =?UTF-8?q?=E4=B8=AA=E8=87=AA=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Exception/ValidateException.php | 2 +- src/Support/Event/ValidateEventAbstract.php | 12 +- src/Support/Event/ValidateResult.php | 8 +- src/Support/Middleware/ValidateMiddleware.php | 56 +++++++- src/Support/Rule/BaseRule.php | 6 +- src/Support/Storage/ValidateCollection.php | 4 +- src/Support/Storage/ValidateConfig.php | 135 +++++++++++++----- src/Support/Storage/ValidateHandler.php | 13 +- src/Support/helpers.php | 10 +- src/Validate.php | 53 ++++--- 10 files changed, 209 insertions(+), 90 deletions(-) diff --git a/src/Exception/ValidateException.php b/src/Exception/ValidateException.php index 6953926..88f51e1 100644 --- a/src/Exception/ValidateException.php +++ b/src/Exception/ValidateException.php @@ -26,7 +26,7 @@ class ValidateException extends Exception parent::__construct($message, $code, $previous); } - public function getData() + public function getData(): array { return $this->data; } diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index 556b42a..d5a3bff 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -59,20 +59,20 @@ abstract class ValidateEventAbstract implements ValidateEventInterface return $next($data, $request); } - final public function setSceneName(?string $sceneName) - { + final public function setSceneName(?string $sceneName): ValidateEventAbstract + { $this->sceneName = $sceneName; return $this; } - final public function setController(string $controller) - { + final public function setController(string $controller): ValidateEventAbstract + { $this->controller = $controller; return $this; } - final public function setMethod(string $method) - { + final public function setMethod(string $method): ValidateEventAbstract + { $this->method = $method; return $this; } diff --git a/src/Support/Event/ValidateResult.php b/src/Support/Event/ValidateResult.php index 7bf2f35..3bff06f 100644 --- a/src/Support/Event/ValidateResult.php +++ b/src/Support/Event/ValidateResult.php @@ -28,13 +28,13 @@ class ValidateResult $this->request = $request; } - public function getData() - { + public function getData(): array + { return $this->data; } - public function getRequest() - { + public function getRequest(): RequestInterface + { return $this->request; } } diff --git a/src/Support/Middleware/ValidateMiddleware.php b/src/Support/Middleware/ValidateMiddleware.php index de26772..c1993a7 100644 --- a/src/Support/Middleware/ValidateMiddleware.php +++ b/src/Support/Middleware/ValidateMiddleware.php @@ -16,7 +16,7 @@ use Exception; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use W7\Core\Facades\Context; +use W7\Facade\Context; use W7\Core\Middleware\MiddlewareAbstract; use W7\Http\Message\Server\Request; use W7\Validate\Support\Storage\ValidateConfig; @@ -47,12 +47,54 @@ class ValidateMiddleware extends MiddlewareAbstract $route = $request->getAttribute('route'); $controller = $route['controller'] ?? ''; $scene = $route['method'] ?? ''; - - $validate = str_replace(ValidateConfig::instance()->controllerPath, '', $controller); - $_namespace = explode('\\', $validate); - $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); - $validate = ValidateConfig::instance()->validatePath . implode('\\', $_namespace) . '\\' . $fileName; - + $haveLink = false; + $validate = ''; + + $validateLink = ValidateConfig::instance()->getValidateLink($controller); + if (!empty($validateLink)) { + # 为指定的控制器方法指定了验证器 + if (isset($validateLink[$scene]) || isset($validateLink['!__other__'])) { + if (isset($validateLink['!__other__'])) { + $method = '!__other__'; + } else { + $method = $scene; + } + + # 为指定的验证器指定了验证场景 + if (is_array($validateLink[$method])) { + if (count($validateLink[$method]) >= 2) { + $validate = $validateLink[$method][0]; + $scene = $validateLink[$method][1]; + $haveLink = true; + } + } else { + $validate = $validateLink[$method]; + $haveLink = true; + } + } + } + + if (false === $haveLink) { + # 处理指定了路径的控制器 + $controllerPath = ''; + $validatePath = ''; + foreach (ValidateConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { + if (false !== strpos($controller, $_controllerPath)) { + $controllerPath = $_controllerPath; + $validatePath = $_validatePath; + break; + } + } + if (empty($controllerPath)) { + return true; + } + + $validate = str_replace($controllerPath, '', $controller); + $_namespace = explode('\\', $validate); + $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); + $validate = $validatePath . implode('\\', $_namespace) . '\\' . $fileName; + } + if (class_exists($validate)) { if (is_subclass_of($validate, Validate::class)) { /** @var Validate $validator */ diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index 70cd187..adafcda 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -18,18 +18,18 @@ abstract class BaseRule implements Rule { protected $message = ''; - public function setMessage(string $message) + public function setMessage(string $message): BaseRule { $this->message = $message; return $this; } - public function getMessage() + public function getMessage(): string { return $this->message; } - public function message() + public function message(): string { return $this->getMessage(); } diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 136cc50..bb53bac 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -18,7 +18,7 @@ use Illuminate\Support\Collection; class ValidateCollection extends Collection { - public function has($key) + public function has($key): bool { $keys = is_array($key) ? $key : func_get_args(); @@ -49,7 +49,7 @@ class ValidateCollection extends Collection return parent::get($key, $default); } - public function set($key, $value) + public function set($key, $value): ValidateCollection { Arr::set($this->items, $key, $value); return $this; diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index cf72d8c..833651b 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -12,55 +12,124 @@ namespace W7\Validate\Support\Storage; -use Exception; use W7\Core\Helper\Traiter\InstanceTraiter; -/** - * Class ValidateConfig - * @package W7\Validate\Support\Storage - * @method ValidateConfig rulesPath(string $path) - * @method ValidateConfig controllerPath(string $path) - * @method ValidateConfig validatePath(string $path) - * @property-read string $rulesPath - * @property-read string $controllerPath - * @property-read string $validatePath - */ class ValidateConfig { use InstanceTraiter; /** * 自定义规则命名空间前缀 - * @var string + * @var array */ - protected $rulesPath = ''; - - /** @var string */ - protected $controllerPath = null; - - /** @var string */ - protected $validatePath = null; - - public function __get($name) + protected $rulesPath = []; + + /** + * 自动加载验证器规则 + * @var array + */ + protected $autoValidatePath = []; + + /** + * 验证器具体关联 + * @var array + */ + protected $validateLink = []; + + /** + * 设置自动加载验证器规则 + * @param string $controllerPath 控制器路径 + * @param string $validatePath 验证器路径 + * @return $this + */ + public function setAutoValidatePath(string $controllerPath, string $validatePath): ValidateConfig + { + $this->autoValidatePath[$controllerPath] = $validatePath; + return $this; + } + + /** + * 设置验证器关联 + * @param string|string[] $controller

控制器完整命名空间

+ * 如需指定方法,请传数组,第二个元素为方法名 + * @param string|string[] $validate

验证器完整命名空间

+ * 如需指定场景,请传数组,第二个元素为场景名 + * @return $this + */ + public function setValidateLink($controller, $validate):ValidateConfig { - if (false === property_exists($this, $name)) { - throw new Exception('Unknown property:' . $name); + if (is_array($controller)) { + $controllers = $controller; + $controller = $controllers[0]; + $method = $controllers[1]; + # 数组中不可以存在 “\” 符号 + $controller = md5($controller); + if (count($controllers) >= 2) { + if (isset($this->validateLink[$controller])) { + $_validate = $this->validateLink[$controller]; + $_validate = array_merge($_validate, [ + $method => $validate + ]); + $this->validateLink[$controller] = $_validate; + } else { + $this->validateLink[$controller] = [ + $method => $validate + ]; + } + } + } else { + $controller = md5($controller); + if (isset($this->validateLink[$controller])) { + $this->validateLink[$controller]['!__other__'] = $validate; + } else { + $this->validateLink[$controller] = [ + '!__other__' => $validate + ]; + } } - - return $this->$name; + return $this; } - - public function __call($name, $args) + + /** + * 获取验证器具体关联 + * @param string|null $controller 验证器完整命名空间 + * @return array + */ + public function getValidateLink(?string $controller = null): array { - if (false === property_exists($this, $name)) { - throw new Exception('Unknown property: ' . $name); + if (null === $controller) { + return $this->validateLink; } - - $this->$name = $args[0]; + return $this->validateLink[md5($controller)] ?? []; + } + +/** + * 设置自定义规则命名空间前缀,如设置多个则全部生效 + * @param string $rulesPath 自定义规则命名空间前缀 + * @return $this + */ + public function setRulesPath(string $rulesPath): ValidateConfig + { + $this->rulesPath[] = $rulesPath; + $this->rulesPath = array_unique($this->rulesPath); return $this; } - - public function __clone() + + /** + * 获取自定义规则命名空间前缀 + * @return array + */ + public function getRulePath(): array + { + return $this->rulesPath; + } + + /** + * 获取自动加载验证器规则 + * @return array + */ + public function getAutoValidatePath(): array { + return $this->autoValidatePath; } } diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index d877565..6206c7a 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -12,6 +12,7 @@ namespace W7\Validate\Support\Storage; +use Closure; use Psr\Http\Message\RequestInterface; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Event\ValidateEventAbstract; @@ -49,8 +50,8 @@ class ValidateHandler $this->method = $route['method'] ?? ''; } - protected function carry() - { + protected function carry(): Closure + { return function ($stack, $pipe) { return function ($data, $request) use ($stack, $pipe) { return $pipe($data, $request, $stack); @@ -58,8 +59,8 @@ class ValidateHandler }; } - protected function pipes(string $method) - { + protected function pipes(string $method): array + { return array_map(function ($middleware) use ($method) { return function ($data, $request, $next) use ($middleware, $method) { list($callback, $param) = $middleware; @@ -77,8 +78,8 @@ class ValidateHandler }, $this->handlers); } - protected function destination() - { + protected function destination(): Closure + { return function ($data, $request) { return new ValidateResult($data, $request); }; diff --git a/src/Support/helpers.php b/src/Support/helpers.php index e322428..cf3cab1 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -11,7 +11,7 @@ */ use Psr\Http\Message\ServerRequestInterface; -use W7\Core\Facades\Context; +use W7\Facade\Context; use W7\Validate\Support\Storage\ValidateCollection; if (!function_exists('validate_collect')) { @@ -20,8 +20,8 @@ if (!function_exists('validate_collect')) { * @param null $value * @return ValidateCollection */ - function validate_collect($value = null) - { + function validate_collect($value = null): ValidateCollection + { return new ValidateCollection($value); } } @@ -32,8 +32,8 @@ if (!function_exists('get_validate_data')) { * @param ServerRequestInterface|null $request 请求示例,如果为null,则自动从上下文中获取 * @return ValidateCollection 返回验证器集合ValidateCollection类型 */ - function get_validate_data(ServerRequestInterface $request = null) - { + function get_validate_data(ServerRequestInterface $request = null): ValidateCollection + { if (null === $request) { $request = Context::getRequest(); } diff --git a/src/Validate.php b/src/Validate.php index 844eba9..737d72a 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -18,8 +18,8 @@ use Illuminate\Support\Fluent; use Illuminate\Validation\ValidationException; use LogicException; use Psr\Http\Message\RequestInterface; -use W7\Core\Facades\Context; -use W7\Core\Facades\Validator; +use W7\Facade\Context; +use W7\Facade\Validator; use W7\Http\Message\Server\Request; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Event\ValidateResult; @@ -103,7 +103,7 @@ class Validate * @return array 返回验证成功后的数据 * @throws ValidateException */ - public function check(array $data) + public function check(array $data): array { try { $this->checkData = $data; @@ -125,7 +125,7 @@ class Validate } } - private function handleEvent(array $data, string $method) + private function handleEvent(array $data, string $method): array { $request = $this->request ?: Context::getRequest(); $request = $request ?: new Request('', null); @@ -140,7 +140,7 @@ class Validate throw new LogicException('Validate event return type error'); } - public function getRequest() + public function getRequest(): ?RequestInterface { return $this->request; } @@ -151,7 +151,7 @@ class Validate $this->handlers = []; } - private function getSceneRules() + private function getSceneRules(): array { $this->init(); $this->addHandler($this->handler); @@ -183,7 +183,7 @@ class Validate return $this->checkRule->toArray(); } - private function getExtendsName(string $rule, string $field = null) + private function getExtendsName(string $rule, string $field = null): string { # 取回真实的自定义规则方法名称,以及修改对应的错误消息 if (in_array($rule, self::$extendName)) { @@ -197,7 +197,7 @@ class Validate return $rule; } - private function makeMessageName(string $field, string $rule) + private function makeMessageName(string $field, string $rule): string { if (false !== strpos($rule, ':')) { $rule = substr($rule, 0, strpos($rule, ':')); @@ -224,7 +224,7 @@ class Validate } } - private function getScene(?string $name = null) + private function getScene(?string $name = null): Validate { if (empty($name)) { $this->checkRule = collect($this->rule); @@ -279,12 +279,19 @@ class Validate return $this; } + /** + * @param string $ruleName + * @return false|mixed|Closure + */ private function getRuleClass(string $ruleName) { - $ruleNameSpace = ValidateConfig::instance()->rulesPath . ucfirst($ruleName); - if (class_exists($ruleNameSpace)) { - return new $ruleNameSpace(); + foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { + $ruleNameSpace = $rulesPath . ucfirst($ruleName); + if (class_exists($ruleNameSpace)) { + return new $ruleNameSpace(); + } } + return false; } @@ -312,7 +319,7 @@ class Validate * @param string $name * @return $this */ - public function scene(string $name) + public function scene(string $name): Validate { $this->currentScene = $name; return $this; @@ -323,7 +330,7 @@ class Validate * @param mixed ...$params * @return $this */ - public function handler(string $handler, ...$params) + public function handler(string $handler, ...$params): Validate { $this->handlers[] = [$handler,$params]; return $this; @@ -335,7 +342,7 @@ class Validate * @param array $fields 字段名 * @return $this */ - public function only(array $fields) + public function only(array $fields): Validate { $this->checkRule = $this->checkRule->only($fields); return $this; @@ -348,7 +355,7 @@ class Validate * @param string $rule 验证规则 * @return $this */ - public function append(string $field, string $rule) + public function append(string $field, string $rule): Validate { if (isset($this->checkRule[$field])) { if (is_array($this->checkRule[$field])) { @@ -373,7 +380,7 @@ class Validate * @param string|null $rule 验证规则 null 移除所有规则 * @return $this */ - public function remove(string $field, ?string $rule = null) + public function remove(string $field, ?string $rule = null): Validate { $removeRule = $rule; if (is_string($rule) && false !== strpos($rule, '|')) { @@ -421,7 +428,7 @@ class Validate * @param callable $callback 回调方法,返回true获取具体规则生效 * @return $this */ - public function sometimes($attribute, $rules, callable $callback) + public function sometimes($attribute, $rules, callable $callback): Validate { $data = new Fluent($this->checkData); $result = $callback($data); @@ -452,7 +459,7 @@ class Validate * @param null $rule 验证字段 * @return array|mixed|null */ - public function getRules($rule = null) + public function getRules($rule = null): ?array { if (null === $rule) { return $this->rule; @@ -471,7 +478,7 @@ class Validate * @param array|null $rules [字段 => 规则] 如果$rules为null,则清空全部验证规则 * @return $this */ - public function setRules(?array $rules = null) + public function setRules(?array $rules = null): Validate { if (null === $rules) { $this->rule = []; @@ -486,7 +493,7 @@ class Validate * @param string|null $rule 如果第一个值为字段名,则第二个值则为规则,否则请留空 * @return array|mixed|null */ - public function getMessages($key = null, ?string $rule = null) + public function getMessages($key = null, ?string $rule = null): ?array { if (null === $key) { return $this->message; @@ -511,7 +518,7 @@ class Validate * @param array|null $message [字段.规则 => 验证消息] 如果$message为null,则清空全部验证消息 * @return $this */ - public function setMessages(?array $message = null) + public function setMessages(?array $message = null): Validate { if (null === $message) { $this->message = []; @@ -527,7 +534,7 @@ class Validate * @param array|null $scene [场景 => [字段]] 如果$scene为null,则清空全部验证场景 * @return $this */ - public function setScene(?array $scene = null) + public function setScene(?array $scene = null): Validate { if (null === $scene) { $this->scene = []; -- Gitee From 3f67b63b063d01fa33cd7057d41e7a5901cf81ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 9 Dec 2020 11:45:23 +0800 Subject: [PATCH 017/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E6=89=BE?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E9=AA=8C=E8=AF=81=E5=99=A8=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Middleware/ValidateMiddleware.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/Middleware/ValidateMiddleware.php b/src/Support/Middleware/ValidateMiddleware.php index c1993a7..013f2cb 100644 --- a/src/Support/Middleware/ValidateMiddleware.php +++ b/src/Support/Middleware/ValidateMiddleware.php @@ -86,7 +86,7 @@ class ValidateMiddleware extends MiddlewareAbstract } } if (empty($controllerPath)) { - return true; + return false; } $validate = str_replace($controllerPath, '', $controller); -- Gitee From 323a091ef742eb73d950e9a506abef018d201a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 9 Dec 2020 14:51:58 +0800 Subject: [PATCH 018/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E7=94=B1?= =?UTF-8?q?=E4=BA=8E=E8=BF=94=E5=9B=9E=E7=B1=BB=E5=9E=8B=E7=9A=84=E9=99=90?= =?UTF-8?q?=E5=AE=9A=E5=AF=BC=E8=87=B4=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 737d72a..ee6814a 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -459,7 +459,7 @@ class Validate * @param null $rule 验证字段 * @return array|mixed|null */ - public function getRules($rule = null): ?array + public function getRules($rule = null) { if (null === $rule) { return $this->rule; @@ -493,7 +493,7 @@ class Validate * @param string|null $rule 如果第一个值为字段名,则第二个值则为规则,否则请留空 * @return array|mixed|null */ - public function getMessages($key = null, ?string $rule = null): ?array + public function getMessages($key = null, ?string $rule = null) { if (null === $key) { return $this->message; -- Gitee From 67ac5a6d376bffe8f8c8a51fdfd7ce62db5e820d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 17 Dec 2020 15:22:01 +0800 Subject: [PATCH 019/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E6=96=B9=E6=B3=95=E6=90=BA?= =?UTF-8?q?=E5=B8=A6=E5=8F=82=E6=95=B0=E5=90=8E=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index ee6814a..bf9f15b 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -183,8 +183,17 @@ class Validate return $this->checkRule->toArray(); } - private function getExtendsName(string $rule, string $field = null): string + private function getExtendsName(string $rule, string $field = null):string { + $param = null; + if (false !== strpos($rule, ':')) { + $rules = explode(':', $rule, 2); + $rule = $rules[0]; + if (count($rules) >= 2) { + $param = $rules[1]; + } + } + # 取回真实的自定义规则方法名称,以及修改对应的错误消息 if (in_array($rule, self::$extendName)) { $ruleName = md5(get_called_class() . $rule); @@ -192,7 +201,12 @@ class Validate if (null !== $field && isset($this->message[$field . '.' . $rule])) { $this->message[$ruleName] = $this->message[$field . '.' . $rule]; } - return $ruleName; + + $rule = $ruleName; + } + + if (!empty($param)) { + $rule = $rule . ':' . $param; } return $rule; } -- Gitee From 48e31e0f764085fc3053a2a059a4bc83be9cf941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 23 Dec 2020 10:31:25 +0800 Subject: [PATCH 020/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E8=A7=84?= =?UTF-8?q?=E5=88=99=E5=8F=82=E6=95=B0=E4=B8=BA0=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index bf9f15b..70e99c2 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -185,7 +185,7 @@ class Validate private function getExtendsName(string $rule, string $field = null):string { - $param = null; + $param = ''; if (false !== strpos($rule, ':')) { $rules = explode(':', $rule, 2); $rule = $rules[0]; @@ -205,7 +205,7 @@ class Validate $rule = $ruleName; } - if (!empty($param)) { + if ('' !== $param) { $rule = $rule . ':' . $param; } return $rule; -- Gitee From dde383daafdef23f9bc683edab8df4dc91901a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 31 Dec 2020 17:03:39 +0800 Subject: [PATCH 021/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0Bail=E9=80=89?= =?UTF-8?q?=E9=A1=B9=EF=BC=8C=E9=BB=98=E8=AE=A4=E5=BC=80=E5=90=AF=E9=A6=96?= =?UTF-8?q?=E6=AC=A1=E9=AA=8C=E8=AF=81=E5=A4=B1=E8=B4=A5=E5=90=8E=E5=81=9C?= =?UTF-8?q?=E6=AD=A2=E8=BF=90=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 70e99c2..74e53aa 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -53,9 +53,18 @@ class Validate */ protected $handler = []; - /** @var array */ + /** + * 字段名称 + * @var array + */ protected $customAttributes = []; + /** + * 是否首次验证失败后停止运行 + * @var bool + */ + protected $bail = true; + /** * 当前验证场景 * @var string @@ -108,7 +117,10 @@ class Validate try { $this->checkData = $data; $rule = $this->getSceneRules(); - $data = $this->handleEvent($data, 'beforeValidate'); + if ($this->bail) { + $rule = $this->addBailRule($rule); + } + $data = $this->handleEvent($data, 'beforeValidate'); /** @var \Illuminate\Validation\Validator $v */ $v = Validator::make($data, $rule, $this->message, $this->customAttributes); $data = $this->handleEvent($v->validate(), 'afterValidate'); @@ -238,6 +250,18 @@ class Validate } } + private function addBailRule(array $rules):array + { + foreach ($rules as $key => $rule) { + if (!in_array('bail', $rule)) { + array_unshift($rule, 'bail'); + $rules[$key] = $rule; + } + } + + return $rules; + } + private function getScene(?string $name = null): Validate { if (empty($name)) { -- Gitee From 3f830f00ef272a813c225df2a690c2a24d2187f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 12 Jan 2021 10:26:49 +0800 Subject: [PATCH 022/152] =?UTF-8?q?[A]=20=E6=94=AF=E6=8C=81=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E4=BC=A0=E9=80=92=E5=8F=82?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 74e53aa..6897f34 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -197,14 +197,7 @@ class Validate private function getExtendsName(string $rule, string $field = null):string { - $param = ''; - if (false !== strpos($rule, ':')) { - $rules = explode(':', $rule, 2); - $rule = $rules[0]; - if (count($rules) >= 2) { - $param = $rules[1]; - } - } + list($rule, $param) = $this->getKeyAndParam($rule, false); # 取回真实的自定义规则方法名称,以及修改对应的错误消息 if (in_array($rule, self::$extendName)) { @@ -223,6 +216,25 @@ class Validate return $rule; } + private function getKeyAndParam(string $value, bool $parsing = false): array + { + $param = ''; + if (false !== strpos($value, ':')) { + $arg = explode(':', $value, 2); + $key = $arg[0]; + if (count($arg) >= 2) { + $param = $arg[1]; + } + } else { + $key = $value; + } + + if ($parsing) { + $param = explode(',', $param); + } + return [$key,$param]; + } + private function makeMessageName(string $field, string $rule): string { if (false !== strpos($rule, ':')) { @@ -323,10 +335,12 @@ class Validate */ private function getRuleClass(string $ruleName) { + list($ruleName, $param) = $this->getKeyAndParam($ruleName, true); + foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { $ruleNameSpace = $rulesPath . ucfirst($ruleName); if (class_exists($ruleNameSpace)) { - return new $ruleNameSpace(); + return new $ruleNameSpace(...$param); } } -- Gitee From d24c685894e76e00d91ed615dfc6b6aadff3ce18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 12 Jan 2021 11:37:51 +0800 Subject: [PATCH 023/152] =?UTF-8?q?[U]=20=E9=80=82=E9=85=8D=E6=96=B0?= =?UTF-8?q?=E7=89=88=E8=BD=AF=E6=93=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- src/Support/Middleware/ValidateMiddleware.php | 18 ++++++++++++------ src/Validate.php | 5 ++++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 818d85c..92c515c 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ ], "require": { "php": "^7.2|^8.0", - "w7/rangine": "^2.3" + "w7/rangine": "^2.4.7" }, "require-dev": { "phpunit/phpunit" : "8.5.8.*" diff --git a/src/Support/Middleware/ValidateMiddleware.php b/src/Support/Middleware/ValidateMiddleware.php index 013f2cb..189705f 100644 --- a/src/Support/Middleware/ValidateMiddleware.php +++ b/src/Support/Middleware/ValidateMiddleware.php @@ -16,6 +16,7 @@ use Exception; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; +use W7\Core\Route\Route; use W7\Facade\Context; use W7\Core\Middleware\MiddlewareAbstract; use W7\Http\Message\Server\Request; @@ -35,18 +36,23 @@ class ValidateMiddleware extends MiddlewareAbstract $data = $validator->check($data); $request = $validator->getRequest(); } - + /** @var Request $request */ $request = $request->withAttribute('validate', $data); Context::setRequest($request); return $handler->handle($request); } - + final public function getValidate(ServerRequestInterface $request) { - $route = $request->getAttribute('route'); - $controller = $route['controller'] ?? ''; - $scene = $route['method'] ?? ''; + /** @var Route $route */ + $route = $request->getAttribute('route'); + $handler = $route->handler; + if (!is_array($handler) || 2 !== count($handler)) { + return false; + } + $controller = $handler[0] ?? ''; + $scene = $handler[1] ?? ''; $haveLink = false; $validate = ''; @@ -102,7 +108,7 @@ class ValidateMiddleware extends MiddlewareAbstract $validator->scene($scene); return $validator; } - + throw new Exception("The given 'Validate' " . $validate . ' has to be a subtype of W7\Validate\Validate'); } return false; diff --git a/src/Validate.php b/src/Validate.php index 6897f34..0243733 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -139,6 +139,9 @@ class Validate private function handleEvent(array $data, string $method): array { + if (empty($this->handlers)){ + return $data; + } $request = $this->request ?: Context::getRequest(); $request = $request ?: new Request('', null); $result = (new ValidateHandler($data, $this->handlers, $request, $this->currentScene))->handle($method); @@ -336,7 +339,7 @@ class Validate private function getRuleClass(string $ruleName) { list($ruleName, $param) = $this->getKeyAndParam($ruleName, true); - + foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { $ruleNameSpace = $rulesPath . ucfirst($ruleName); if (class_exists($ruleNameSpace)) { -- Gitee From 3cccf1d77da79e0b2744ca347ab853ce969dbc5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 13 Jan 2021 11:28:00 +0800 Subject: [PATCH 024/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E7=9A=84=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8C=96=E9=94=99=E8=AF=AF=E6=B6=88=E6=81=AF=20[D]=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=BA=8B=E4=BB=B6=E4=B8=AD=E7=9A=84=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E6=8E=A7=E5=88=B6=E5=99=A8=EF=BC=8C=E6=96=B9=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Event/ValidateEventAbstract.php | 31 ++-------- src/Support/Rule/BaseRule.php | 18 ++++-- src/Support/Storage/ValidateHandler.php | 20 ++----- src/Validate.php | 66 +++++++++++++++++++-- 4 files changed, 85 insertions(+), 50 deletions(-) diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index d5a3bff..bf4e479 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -23,18 +23,6 @@ abstract class ValidateEventAbstract implements ValidateEventInterface */ protected $sceneName; - /** - * 当前控制器名称 - * @var string - */ - protected $controller; - - /** - * 当前操作方法 - * @var string - */ - protected $method; - /** * 场景验证前 * @param array $data 用户输入的数据 @@ -59,21 +47,14 @@ abstract class ValidateEventAbstract implements ValidateEventInterface return $next($data, $request); } + /** + * 写入当前的验证场景名称 + * @param string|null $sceneName + * @return $this + */ final public function setSceneName(?string $sceneName): ValidateEventAbstract - { + { $this->sceneName = $sceneName; return $this; } - - final public function setController(string $controller): ValidateEventAbstract - { - $this->controller = $controller; - return $this; - } - - final public function setMethod(string $method): ValidateEventAbstract - { - $this->method = $method; - return $this; - } } diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index adafcda..3340407 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -16,19 +16,29 @@ use Illuminate\Contracts\Validation\Rule; abstract class BaseRule implements Rule { + /** + * 错误消息,支持format字符串 + * @var string + */ protected $message = ''; - + + /** + * 用于format错误消息的参数 + * @var array + */ + protected $messageParam = []; + public function setMessage(string $message): BaseRule { $this->message = $message; return $this; } - + public function getMessage(): string { - return $this->message; + return vsprintf($this->message, $this->messageParam); } - + public function message(): string { return $this->getMessage(); diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index 6206c7a..23fc304 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -32,26 +32,16 @@ class ValidateHandler /** @var string */ protected $sceneName = null; - /** @var string */ - protected $controller; - - /** @var string */ - protected $method; - public function __construct(array $data, array $handlers, RequestInterface $request, string $sceneName = null) { $this->data = $data; $this->request = $request; $this->handlers = $handlers; $this->sceneName = $sceneName; - - $route = $request->getAttribute('route'); - $this->controller = $route['controller'] ?? ''; - $this->method = $route['method'] ?? ''; } protected function carry(): Closure - { + { return function ($stack, $pipe) { return function ($data, $request) use ($stack, $pipe) { return $pipe($data, $request, $stack); @@ -60,16 +50,14 @@ class ValidateHandler } protected function pipes(string $method): array - { + { return array_map(function ($middleware) use ($method) { return function ($data, $request, $next) use ($middleware, $method) { list($callback, $param) = $middleware; if (class_exists($callback) && is_subclass_of($callback, ValidateEventAbstract::class)) { /** @var ValidateEventAbstract $handler */ $handler = new $callback(...$param); - $handler->setSceneName($this->sceneName) - ->setController($this->controller) - ->setMethod($this->method); + $handler->setSceneName($this->sceneName); return call_user_func([$handler, $method], $data, $request, $next); } else { throw new ValidateException('Event error or nonexistence'); @@ -79,7 +67,7 @@ class ValidateHandler } protected function destination(): Closure - { + { return function ($data, $request) { return new ValidateResult($data, $request); }; diff --git a/src/Validate.php b/src/Validate.php index 0243733..8433df1 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -108,8 +108,8 @@ class Validate /** * 自动验证 - * @param array $data - * @return array 返回验证成功后的数据 + * @param array $data 待验证的数据 + * @return array * @throws ValidateException */ public function check(array $data): array @@ -137,6 +137,13 @@ class Validate } } + /** + * 验证事件处理 + * @param array $data 验证的数据 + * @param string $method 事件名称 + * @return array + * @throws ValidateException + */ private function handleEvent(array $data, string $method): array { if (empty($this->handlers)){ @@ -155,17 +162,28 @@ class Validate throw new LogicException('Validate event return type error'); } + /** + * 获取请求类 + * @return RequestInterface|null + */ public function getRequest(): ?RequestInterface { return $this->request; } + /** + * 初始化验证 + */ private function init() { $this->checkRule = []; $this->handlers = []; } + /** + * 获取当前场景下需要验证的规则 + * @return array + */ private function getSceneRules(): array { $this->init(); @@ -198,6 +216,13 @@ class Validate return $this->checkRule->toArray(); } + /** + * 获取扩展方法的名称 + * 由于为了区分多个验证器的相同自定义方法名,对方法名做了处理,此方法为了使规则和处理后的方法名对应上 + * @param string $rule 规则名称 + * @param string|null $field 字段 + * @return string + */ private function getExtendsName(string $rule, string $field = null):string { list($rule, $param) = $this->getKeyAndParam($rule, false); @@ -219,6 +244,12 @@ class Validate return $rule; } + /** + * 获取规则的名称和参数 + * @param string $value 规则 + * @param bool $parsing 是否解析参数,默认为false + * @return array + */ private function getKeyAndParam(string $value, bool $parsing = false): array { $param = ''; @@ -238,6 +269,12 @@ class Validate return [$key,$param]; } + /** + * 生成错误消息的名称 + * @param string $field 字段 + * @param string $rule 规则 + * @return string + */ private function makeMessageName(string $field, string $rule): string { if (false !== strpos($rule, ':')) { @@ -246,6 +283,10 @@ class Validate return $field . '.' . $rule; } + /** + * 添加事件 + * @param $handlers + */ private function addHandler($handlers) { if (is_string($handlers)) { @@ -265,6 +306,11 @@ class Validate } } + /** + * 添加bail规则 + * @param array $rules 原规则 + * @return array + */ private function addBailRule(array $rules):array { foreach ($rules as $key => $rule) { @@ -277,6 +323,12 @@ class Validate return $rules; } + /** + * 进入场景 + * @param string|null $name 场景名称 + * @return Validate + * @throws ValidateException + */ private function getScene(?string $name = null): Validate { if (empty($name)) { @@ -333,7 +385,9 @@ class Validate } /** - * @param string $ruleName + * 获取自定义规则的实例类 + * + * @param string $ruleName 自定义规则名称 * @return false|mixed|Closure */ private function getRuleClass(string $ruleName) @@ -381,8 +435,10 @@ class Validate } /** - * @param string $handler - * @param mixed ...$params + * 加入事件 + * + * @param string $handler 事件的完整类名,完整命名空间字符串或者加::class + * @param mixed ...$params 要传递给事件的参数 * @return $this */ public function handler(string $handler, ...$params): Validate -- Gitee From 81c1e367a055c73868b855e34a6c52152b936eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 15 Jan 2021 16:23:46 +0800 Subject: [PATCH 025/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0=E6=9C=80?= =?UTF-8?q?=E4=BD=8E=E6=94=AF=E6=8C=81=E5=88=B0PHP7.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- src/Exception/ValidateException.php | 3 +- src/Support/Event/ValidateEventAbstract.php | 4 +-- src/Support/Event/ValidateResult.php | 12 +++---- src/Support/Rule/BaseRule.php | 4 +-- src/Support/Storage/ValidateCollection.php | 37 +++++++++++++++++++-- src/Support/Storage/ValidateConfig.php | 16 ++++----- src/Support/Storage/ValidateHandler.php | 16 ++++----- src/Validate.php | 35 +++++++++---------- 9 files changed, 78 insertions(+), 51 deletions(-) diff --git a/composer.json b/composer.json index 92c515c..1432a03 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "validate" ], "require": { - "php": "^7.2|^8.0", + "php": "^7.4|^8.0", "w7/rangine": "^2.4.7" }, "require-dev": { diff --git a/src/Exception/ValidateException.php b/src/Exception/ValidateException.php index 88f51e1..da2a569 100644 --- a/src/Exception/ValidateException.php +++ b/src/Exception/ValidateException.php @@ -17,8 +17,7 @@ use Throwable; class ValidateException extends Exception { - /** @var array */ - protected $data = []; + protected array $data = []; public function __construct($message = '', $code = 0, array $data = [], Throwable $previous = null) { diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index bf4e479..2b59695 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -19,9 +19,9 @@ abstract class ValidateEventAbstract implements ValidateEventInterface { /** * 当前验证场景 - * @var string + * @var ?string */ - protected $sceneName; + protected ?string $sceneName; /** * 场景验证前 diff --git a/src/Support/Event/ValidateResult.php b/src/Support/Event/ValidateResult.php index 3bff06f..a9db160 100644 --- a/src/Support/Event/ValidateResult.php +++ b/src/Support/Event/ValidateResult.php @@ -16,11 +16,9 @@ use Psr\Http\Message\RequestInterface; class ValidateResult { - /** @var array */ - protected $data; - - /** @var RequestInterface */ - protected $request; + protected array $data; + + protected RequestInterface $request; public function __construct(array $data, RequestInterface $request) { @@ -29,12 +27,12 @@ class ValidateResult } public function getData(): array - { + { return $this->data; } public function getRequest(): RequestInterface - { + { return $this->request; } } diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index 3340407..2e9c6b3 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -20,13 +20,13 @@ abstract class BaseRule implements Rule * 错误消息,支持format字符串 * @var string */ - protected $message = ''; + protected string $message = ''; /** * 用于format错误消息的参数 * @var array */ - protected $messageParam = []; + protected array $messageParam = []; public function setMessage(string $message): BaseRule { diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index bb53bac..6fc9315 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -12,12 +12,19 @@ namespace W7\Validate\Support\Storage; +use ArrayAccess; use Closure; use Illuminate\Support\Arr; use Illuminate\Support\Collection; +use Illuminate\Support\HigherOrderWhenProxy; class ValidateCollection extends Collection { + /** + * 判断集合中是否存在指定的字段 + * @param mixed $key 要验证的字段 + * @return bool + */ public function has($key): bool { $keys = is_array($key) ? $key : func_get_args(); @@ -31,16 +38,36 @@ class ValidateCollection extends Collection return true; } + /** + * 当指定字段存在时执行 + * @param mixed $key 要验证的字段 + * @param callable $callback 存在时执行 + * @param callable|null $default 不存在时执行 + * @return HigherOrderWhenProxy|mixed|ValidateCollection + */ public function whenHas($key, callable $callback, callable $default = null) { return $this->when($this->has($key), $callback, $default); } + /** + * 当指定字段不存在时执行 + * @param mixed $key 要验证的字段 + * @param callable $callback 不存在时执行 + * @param callable|null $default 存在时执行 + * @return HigherOrderWhenProxy|mixed|ValidateCollection + */ public function whenNotHas($key, callable $callback, callable $default = null) { return $this->when(!$this->has($key), $callback, $default); } - + + /** + * 获取指定字段的值 + * @param mixed $key 字段名称 + * @param null $default 默认值 + * @return array|ArrayAccess|mixed + */ public function get($key, $default = null) { if (false !== strpos($key, '.')) { @@ -48,7 +75,13 @@ class ValidateCollection extends Collection } return parent::get($key, $default); } - + + /** + * 在集合中写入指定的值 + * @param mixed $key 要写入的字段 + * @param mixed $value 要写入的值 + * @return $this + */ public function set($key, $value): ValidateCollection { Arr::set($this->items, $key, $value); diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 833651b..88ca35a 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -22,19 +22,19 @@ class ValidateConfig * 自定义规则命名空间前缀 * @var array */ - protected $rulesPath = []; + protected array $rulesPath = []; /** * 自动加载验证器规则 * @var array */ - protected $autoValidatePath = []; + protected array $autoValidatePath = []; /** * 验证器具体关联 * @var array */ - protected $validateLink = []; + protected array $validateLink = []; /** * 设置自动加载验证器规则 @@ -103,11 +103,11 @@ class ValidateConfig return $this->validateLink[md5($controller)] ?? []; } -/** - * 设置自定义规则命名空间前缀,如设置多个则全部生效 - * @param string $rulesPath 自定义规则命名空间前缀 - * @return $this - */ + /** + * 设置自定义规则命名空间前缀,如设置多个则全部生效 + * @param string $rulesPath 自定义规则命名空间前缀 + * @return $this + */ public function setRulesPath(string $rulesPath): ValidateConfig { $this->rulesPath[] = $rulesPath; diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index 23fc304..51b468e 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -20,17 +20,13 @@ use W7\Validate\Support\Event\ValidateResult; class ValidateHandler { - /** @var array */ - protected $handlers = []; - - /** @var array */ - protected $data = []; - - /** @var RequestInterface */ - protected $request; + protected array $handlers = []; + + protected array $data = []; + + protected RequestInterface $request; - /** @var string */ - protected $sceneName = null; + protected ?string $sceneName = null; public function __construct(array $data, array $handlers, RequestInterface $request, string $sceneName = null) { diff --git a/src/Validate.php b/src/Validate.php index 8433df1..02d5bab 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -33,73 +33,73 @@ class Validate * 自定义错误消息 * @var array */ - protected $message = []; + protected array $message = []; /** * 验证规则 * @var array */ - protected $rule = []; + protected array $rule = []; /** * 验证场景数据,key为控制器内的方法 * @var array */ - protected $scene = []; + protected array $scene = []; /** * 全局事件处理器 * @var array */ - protected $handler = []; + protected array $handler = []; /** * 字段名称 * @var array */ - protected $customAttributes = []; + protected array $customAttributes = []; /** * 是否首次验证失败后停止运行 * @var bool */ - protected $bail = true; + protected bool $bail = true; /** * 当前验证场景 - * @var string + * @var ?string */ - private $currentScene = null; + private ?string $currentScene = null; /** * 验证的规则 * @var Collection */ - private $checkRule; + private Collection $checkRule; /** * 扩展方法名 * @var array */ - private static $extendName = []; + private static array $extendName = []; /** * 验证器事件处理类 * @var array */ - private $handlers = []; + private array $handlers = []; /** * Request请求实例 * @var RequestInterface|null */ - protected $request = null; + protected ?RequestInterface $request = null; /** * 当前进行验证的数据 * @var array */ - protected $checkData = []; + protected array $checkData = []; public function __construct(?RequestInterface $request = null) { @@ -146,12 +146,12 @@ class Validate */ private function handleEvent(array $data, string $method): array { - if (empty($this->handlers)){ + if (empty($this->handlers)) { return $data; } $request = $this->request ?: Context::getRequest(); - $request = $request ?: new Request('', null); - $result = (new ValidateHandler($data, $this->handlers, $request, $this->currentScene))->handle($method); + $request ??= new Request('', null); + $result = (new ValidateHandler($data, $this->handlers, $request, $this->currentScene))->handle($method); if (is_string($result)) { throw new ValidateException($result, 403); } elseif ($result instanceof ValidateResult) { @@ -176,13 +176,14 @@ class Validate */ private function init() { - $this->checkRule = []; + $this->checkRule = collect([]); $this->handlers = []; } /** * 获取当前场景下需要验证的规则 * @return array + * @throws ValidateException */ private function getSceneRules(): array { -- Gitee From 0cbc68ec272db786bca08c36b6ad29ae9e9931f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 15 Jan 2021 18:03:43 +0800 Subject: [PATCH 026/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E6=89=A9=E5=B1=95=E7=B1=BB=E5=9E=8B=E8=BD=AC=E6=8D=A2?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Exception/CollectionException.php | 19 ++++ src/Support/Rule/BaseRule.php | 4 +- src/Support/Rule/RuleInterface.php | 34 +++++++ src/Support/Storage/ValidateCollection.php | 100 ++++++++++++++++++++- 4 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 src/Exception/CollectionException.php create mode 100644 src/Support/Rule/RuleInterface.php diff --git a/src/Exception/CollectionException.php b/src/Exception/CollectionException.php new file mode 100644 index 0000000..64fd1c3 --- /dev/null +++ b/src/Exception/CollectionException.php @@ -0,0 +1,19 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Exception; + +use Exception; + +class CollectionException extends Exception +{ +} diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index 2e9c6b3..28292f1 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -12,9 +12,7 @@ namespace W7\Validate\Support\Rule; -use Illuminate\Contracts\Validation\Rule; - -abstract class BaseRule implements Rule +abstract class BaseRule implements RuleInterface { /** * 错误消息,支持format字符串 diff --git a/src/Support/Rule/RuleInterface.php b/src/Support/Rule/RuleInterface.php new file mode 100644 index 0000000..efadc81 --- /dev/null +++ b/src/Support/Rule/RuleInterface.php @@ -0,0 +1,34 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Rule; + +use Illuminate\Contracts\Validation\Rule; + +interface RuleInterface extends Rule +{ + /** + * Determine if the validation rule passes. + * + * @param string $attribute + * @param mixed $value + * @return bool + */ + public function passes($attribute, $value): bool; + + /** + * Get the validation error message. + * + * @return string + */ + public function message(): string; +} diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 6fc9315..71ba5d0 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -17,9 +17,84 @@ use Closure; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\HigherOrderWhenProxy; +use W7\Validate\Exception\CollectionException; class ValidateCollection extends Collection { + private ?string $paramType; + + /** + * 将下一次取出的值强制转为int类型 + * + * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function int(): ValidateCollection + { + $this->paramType = 'int'; + return $this; + } + + /** + * 将下一次取出的值强制转为float类型 + * + * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function float(): ValidateCollection + { + $this->paramType = 'float'; + return $this; + } + + /** + * 将下一次取出的值强制转为string类型 + * + * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function string(): ValidateCollection + { + $this->paramType = 'string'; + return $this; + } + + /** + * 将下一次取出的值强制转为array类型 + * + * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function array(): ValidateCollection + { + $this->paramType = 'array'; + return $this; + } + + /** + * 将下一次取出的值强制转为object类型 + * + * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function object(): ValidateCollection + { + $this->paramType = 'object'; + return $this; + } + + /** + * 将下一次取出的值强制转为bool类型 + * + * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function bool(): ValidateCollection + { + $this->paramType = 'bool'; + return $this; + } + /** * 判断集合中是否存在指定的字段 * @param mixed $key 要验证的字段 @@ -64,16 +139,33 @@ class ValidateCollection extends Collection /** * 获取指定字段的值 - * @param mixed $key 字段名称 - * @param null $default 默认值 + * @param mixed $key 字段名称 + * @param null $default 默认值 * @return array|ArrayAccess|mixed + * @throws CollectionException */ public function get($key, $default = null) { if (false !== strpos($key, '.')) { - return Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); + $value = Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); + } else { + $value = parent::get($key, $default); } - return parent::get($key, $default); + + if (!empty($this->paramType)) { + $error = null; + set_error_handler(function ($type, $msg) use (&$error) { + $error = $msg; + }); + settype($value, $this->paramType); + restore_error_handler(); + $this->paramType = null; + if (!empty($error)) { + throw new CollectionException($error); + } + } + + return $value; } /** -- Gitee From 24bf65e6d793c513eebe529042c94a50506a7859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 19 Jan 2021 14:30:39 +0800 Subject: [PATCH 027/152] =?UTF-8?q?[A]=20=E7=B1=BB=E5=9E=8B=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E5=AF=B9pop,push,shift=E6=96=B9=E6=B3=95=E7=94=9F?= =?UTF-8?q?=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 82 +++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 71ba5d0..4039761 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -26,6 +26,12 @@ class ValidateCollection extends Collection /** * 将下一次取出的值强制转为int类型 * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

* 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 * @return $this */ @@ -38,6 +44,12 @@ class ValidateCollection extends Collection /** * 将下一次取出的值强制转为float类型 * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

* 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 * @return $this */ @@ -50,6 +62,12 @@ class ValidateCollection extends Collection /** * 将下一次取出的值强制转为string类型 * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

* 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 * @return $this */ @@ -62,6 +80,12 @@ class ValidateCollection extends Collection /** * 将下一次取出的值强制转为array类型 * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

* 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 * @return $this */ @@ -74,6 +98,12 @@ class ValidateCollection extends Collection /** * 将下一次取出的值强制转为object类型 * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

* 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 * @return $this */ @@ -86,6 +116,12 @@ class ValidateCollection extends Collection /** * 将下一次取出的值强制转为bool类型 * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

* 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 * @return $this */ @@ -152,6 +188,50 @@ class ValidateCollection extends Collection $value = parent::get($key, $default); } + return $this->typeConversion($value); + } + + /** + * 移除并返回集合的最后一个集合项 + * @return mixed + * @throws CollectionException + */ + public function pop() + { + return $this->typeConversion(parent::pop()); + } + + /** + * 移除并返回集合的第一个集合项 + * @return mixed + * @throws CollectionException + */ + public function shift() + { + return $this->typeConversion(parent::shift()); + } + + /** + * 将指定键对应的值从集合中移除并返回 + * @param mixed $key 字段名称 + * @param null $default 默认值 + * @return mixed + * @throws CollectionException + */ + public function pull($key, $default = null) + { + $value = parent::pull($key, $default); + return $this->typeConversion($value); + } + + /** + * 将值转为指定类型 + * @param $value + * @return mixed + * @throws CollectionException + */ + private function typeConversion($value) + { if (!empty($this->paramType)) { $error = null; set_error_handler(function ($type, $msg) use (&$error) { @@ -164,7 +244,7 @@ class ValidateCollection extends Collection throw new CollectionException($error); } } - + return $value; } -- Gitee From 18d64f754540f24011d4ca9ec4d5d2de2c9aa7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 19 Jan 2021 14:49:09 +0800 Subject: [PATCH 028/152] =?UTF-8?q?[U]=20=E6=A0=B9=E6=8D=AE=E6=96=B0?= =?UTF-8?q?=E8=A7=84=E5=88=99=E8=BF=9B=E8=A1=8C=E6=A0=BC=E5=BC=8F=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .php_cs | 6 ++++++ src/Support/Storage/ValidateConfig.php | 2 +- src/Support/helpers.php | 4 ++-- src/Validate.php | 14 +++++++------- tests/Material/Rules/AlphaNum.php | 16 ++++++++++++---- tests/Material/Rules/ChsAlphaNum.php | 4 ++-- tests/Material/TestArticleValidate.php | 12 ++++++------ tests/Material/TestBaseValidate.php | 5 +++-- tests/TestValidateScene.php | 4 ++-- 9 files changed, 41 insertions(+), 26 deletions(-) diff --git a/.php_cs b/.php_cs index 230a588..390a889 100644 --- a/.php_cs +++ b/.php_cs @@ -46,9 +46,15 @@ $fixers = [ ], // 'braces' => ['position_after_functions_and_oop_constructs' => 'same'], //设置大括号换行,暂时根本Psr 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], //等号对齐、数字箭头符号对齐 + 'whitespace_after_comma_in_array' => true, 'array_syntax' => ['syntax' => 'short'], 'ternary_operator_spaces' => true, 'yoda_style' => true, + 'normalize_index_brace' => true, + 'short_scalar_cast' => true, + 'function_typehint_space' => true, + 'function_declaration' => true, + 'return_type_declaration' => true ]; return PhpCsFixer\Config::create() diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 88ca35a..73cc57d 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -56,7 +56,7 @@ class ValidateConfig * 如需指定场景,请传数组,第二个元素为场景名 * @return $this */ - public function setValidateLink($controller, $validate):ValidateConfig + public function setValidateLink($controller, $validate): ValidateConfig { if (is_array($controller)) { $controllers = $controller; diff --git a/src/Support/helpers.php b/src/Support/helpers.php index cf3cab1..c27bd3e 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -21,7 +21,7 @@ if (!function_exists('validate_collect')) { * @return ValidateCollection */ function validate_collect($value = null): ValidateCollection - { + { return new ValidateCollection($value); } } @@ -33,7 +33,7 @@ if (!function_exists('get_validate_data')) { * @return ValidateCollection 返回验证器集合ValidateCollection类型 */ function get_validate_data(ServerRequestInterface $request = null): ValidateCollection - { + { if (null === $request) { $request = Context::getRequest(); } diff --git a/src/Validate.php b/src/Validate.php index 02d5bab..c5feaec 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -224,7 +224,7 @@ class Validate * @param string|null $field 字段 * @return string */ - private function getExtendsName(string $rule, string $field = null):string + private function getExtendsName(string $rule, string $field = null): string { list($rule, $param) = $this->getKeyAndParam($rule, false); @@ -267,7 +267,7 @@ class Validate if ($parsing) { $param = explode(',', $param); } - return [$key,$param]; + return [$key, $param]; } /** @@ -291,11 +291,11 @@ class Validate private function addHandler($handlers) { if (is_string($handlers)) { - $this->handlers[] = [$handlers,[]]; + $this->handlers[] = [$handlers, []]; } else { foreach ($handlers as $handlerClass => $param) { if (is_int($handlerClass)) { - $this->handlers[] = [$param,[]]; + $this->handlers[] = [$param, []]; } elseif (is_string($handlerClass)) { if (is_array($param)) { $this->handler($handlerClass, ...$param); @@ -312,7 +312,7 @@ class Validate * @param array $rules 原规则 * @return array */ - private function addBailRule(array $rules):array + private function addBailRule(array $rules): array { foreach ($rules as $key => $rule) { if (!in_array('bail', $rule)) { @@ -367,7 +367,7 @@ class Validate )->scene($randScene)->check($this->checkData); } - $use = call_user_func([$this,'use' . ucfirst($use)], $data); + $use = call_user_func([$this, 'use' . ucfirst($use)], $data); if (is_array($use)) { $this->checkRule = collect($this->rule)->only($use); return $this; @@ -444,7 +444,7 @@ class Validate */ public function handler(string $handler, ...$params): Validate { - $this->handlers[] = [$handler,$params]; + $this->handlers[] = [$handler, $params]; return $this; } diff --git a/tests/Material/Rules/AlphaNum.php b/tests/Material/Rules/AlphaNum.php index dbbb427..2ecac95 100644 --- a/tests/Material/Rules/AlphaNum.php +++ b/tests/Material/Rules/AlphaNum.php @@ -1,17 +1,25 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ namespace W7\Tests\Material\Rules; - use W7\Validate\Support\Rule\BaseRule; class AlphaNum extends BaseRule { - protected $message = ':attribute的值只能具有英文字母,数字'; + protected string $message = ':attribute的值只能具有英文字母,数字'; - public function passes($attribute, $value) + public function passes($attribute, $value): bool { return is_scalar($value) && 1 === preg_match('/^[A-Za-z0-9]+$/', (string)$value); } -} \ No newline at end of file +} diff --git a/tests/Material/Rules/ChsAlphaNum.php b/tests/Material/Rules/ChsAlphaNum.php index 28c3f90..ce252ea 100644 --- a/tests/Material/Rules/ChsAlphaNum.php +++ b/tests/Material/Rules/ChsAlphaNum.php @@ -16,9 +16,9 @@ use W7\Validate\Support\Rule\BaseRule; class ChsAlphaNum extends BaseRule { - protected $message = ':attribute的值只能具有中文,字母,数字'; + protected string $message = ':attribute的值只能具有中文,字母,数字'; - public function passes($attribute, $value) + public function passes($attribute, $value): bool { return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u', (string)$value); } diff --git a/tests/Material/TestArticleValidate.php b/tests/Material/TestArticleValidate.php index 6cc590d..dba6af1 100644 --- a/tests/Material/TestArticleValidate.php +++ b/tests/Material/TestArticleValidate.php @@ -16,14 +16,14 @@ use W7\Validate\Validate; class TestArticleValidate extends Validate { - protected $rule = [ + protected array $rule = [ 'id' => 'required|numeric', 'content' => 'required|between:1,2000', 'title' => 'required|between:4,50|alpha', 'type' => 'required|numeric', ]; - protected $message = [ + protected array $message = [ 'id.required' => '缺少参数:文章Id', 'id.numeric' => '参数错误:文章Id', 'content.required' => '文章内容必须填写', @@ -35,15 +35,15 @@ class TestArticleValidate extends Validate 'type.numeric' => '文章分类错误', ]; - protected $scene = [ - 'add' => ['content','title'], + protected array $scene = [ + 'add' => ['content', 'title'], 'save' => ['use' => 'edit'], 'del' => ['id'], ]; public function sceneEdit() { - return $this->only(['id','content','title']) + return $this->only(['id', 'content', 'title']) ->append('id', 'max:10000') ->remove('content', 'between') ->remove('title', null) @@ -52,7 +52,7 @@ class TestArticleValidate extends Validate public function sceneDynamic() { - return $this->only(['title','content']) + return $this->only(['title', 'content']) ->remove('content', 'between'); } } diff --git a/tests/Material/TestBaseValidate.php b/tests/Material/TestBaseValidate.php index 9be4d25..93f0795 100644 --- a/tests/Material/TestBaseValidate.php +++ b/tests/Material/TestBaseValidate.php @@ -20,12 +20,13 @@ class TestBaseValidate extends TestCase public function __construct($name = null, array $data = [], $dataName = '') { $this->rangineInit(); - ValidateConfig::instance()->rulesPath('W7\\Tests\\Material\\Rules\\'); + ValidateConfig::instance()->setRulesPath('W7\\Tests\\Material\\Rules\\'); parent::__construct($name, $data, $dataName); } - private function rangineInit(){ + private function rangineInit() + { !defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 2)); !defined('APP_PATH') && define('APP_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'app'); !defined('RUNTIME_PATH') && define('RUNTIME_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'runtime'); diff --git a/tests/TestValidateScene.php b/tests/TestValidateScene.php index d7b4d32..612d904 100644 --- a/tests/TestValidateScene.php +++ b/tests/TestValidateScene.php @@ -18,8 +18,8 @@ use W7\Validate\Exception\ValidateException; class TestValidateScene extends TestBaseValidate { - /** @var array */ - protected $userInput; + protected array $userInput; + public function __construct($name = null, array $data = [], $dataName = '') { parent::__construct($name, $data, $dataName); -- Gitee From 98f98c3710089b080cae08199f8a06ab9e768252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sun, 21 Feb 2021 16:18:52 +0800 Subject: [PATCH 029/152] =?UTF-8?q?[A]=20=E6=B7=BB=E5=8A=A0=E6=89=80?= =?UTF-8?q?=E6=9C=89=E9=AA=8C=E8=AF=81=E7=9A=84=E5=AD=97=E6=AE=B5=E5=9C=A8?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E6=97=B6=E4=B8=8D=E8=83=BD=E4=B8=BA=E7=A9=BA?= =?UTF-8?q?=EF=BC=8C=E8=A7=84=E5=88=99=E4=B8=AD=E5=B8=A6nullable=E9=99=A4?= =?UTF-8?q?=E5=A4=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/Validate.php b/src/Validate.php index c5feaec..ceb0429 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -65,6 +65,12 @@ class Validate */ protected bool $bail = true; + /** + * 所有验证的字段在存在时不能为空,规则中带nullable除外 + * @var bool + */ + protected bool $filled = true; + /** * 当前验证场景 * @var ?string @@ -120,6 +126,9 @@ class Validate if ($this->bail) { $rule = $this->addBailRule($rule); } + if ($this->filled){ + $rule = $this->addFilledRule($rule); + } $data = $this->handleEvent($data, 'beforeValidate'); /** @var \Illuminate\Validation\Validator $v */ $v = Validator::make($data, $rule, $this->message, $this->customAttributes); @@ -324,6 +333,23 @@ class Validate return $rules; } + /** + * 添加filled规则 + * @param array $rules 原规则 + * @return array + */ + public function addFilledRule(array $rules): array + { + foreach ($rules as $key => $rule) { + if (!in_array('filled', $rule) && !in_array('nullable', $rule)) { + array_unshift($rule, 'filled'); + $rules[$key] = $rule; + } + } + + return $rules; + } + /** * 进入场景 * @param string|null $name 场景名称 -- Gitee From 062273066d16e5a8b6b2cdbecc27929beec45010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 3 Mar 2021 11:02:48 +0800 Subject: [PATCH 030/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E9=A3=8E=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .php_cs | 6 +- composer.json | 5 +- src/Exception/CollectionException.php | 2 +- src/Exception/ValidateException.php | 22 +- src/Support/Event/ValidateEventAbstract.php | 78 +- src/Support/Event/ValidateEventInterface.php | 6 +- src/Support/Event/ValidateResult.php | 38 +- src/Support/Middleware/ValidateMiddleware.php | 162 +- src/Support/Rule/BaseRule.php | 48 +- src/Support/Rule/RuleInterface.php | 30 +- src/Support/Storage/ValidateCollection.php | 444 +++--- src/Support/Storage/ValidateConfig.php | 218 +-- src/Support/Storage/ValidateHandler.php | 118 +- src/Support/helpers.php | 44 +- src/Validate.php | 1306 ++++++++--------- tests/Material/Rules/AlphaNum.php | 14 +- tests/Material/Rules/ChsAlphaNum.php | 14 +- tests/Material/TestArticleValidate.php | 78 +- tests/Material/TestBaseValidate.php | 30 +- tests/TestValidateScene.php | 124 +- 20 files changed, 1393 insertions(+), 1394 deletions(-) diff --git a/.php_cs b/.php_cs index 390a889..7fe86d5 100644 --- a/.php_cs +++ b/.php_cs @@ -42,9 +42,8 @@ $fixers = [ ], 'header_comment' => [ 'comment_type' => 'PHPDoc', - 'header' => SOFT_NAME . " \r\n\r\n(c) We7Team 2019 \r\n\r\nThis is not a free software \r\nUsing it under the license terms\r\nvisited https://www.w7.cc for more details", + 'header' => SOFT_NAME . " \r\n\r\n(c) We7Team 2021 \r\n\r\nThis is not a free software \r\nUsing it under the license terms\r\nvisited https://www.w7.cc for more details", ], - // 'braces' => ['position_after_functions_and_oop_constructs' => 'same'], //设置大括号换行,暂时根本Psr 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], //等号对齐、数字箭头符号对齐 'whitespace_after_comma_in_array' => true, 'array_syntax' => ['syntax' => 'short'], @@ -60,5 +59,4 @@ $fixers = [ return PhpCsFixer\Config::create() ->setRules($fixers) ->setFinder($finder) - ->setIndent("\t") - ->setUsingCache(false); + ->setUsingCache(false); \ No newline at end of file diff --git a/composer.json b/composer.json index 1432a03..e077707 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "w7/rangine": "^2.4.7" }, "require-dev": { - "phpunit/phpunit" : "8.5.8.*" + "phpunit/phpunit" : "^8.5", + "friendsofphp/php-cs-fixer": "^2.18" }, "autoload": { "psr-4": { @@ -32,4 +33,4 @@ "W7\\Tests\\" : "tests/" } } -} \ No newline at end of file +} diff --git a/src/Exception/CollectionException.php b/src/Exception/CollectionException.php index 64fd1c3..ce609a1 100644 --- a/src/Exception/CollectionException.php +++ b/src/Exception/CollectionException.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms diff --git a/src/Exception/ValidateException.php b/src/Exception/ValidateException.php index da2a569..2717785 100644 --- a/src/Exception/ValidateException.php +++ b/src/Exception/ValidateException.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -17,16 +17,16 @@ use Throwable; class ValidateException extends Exception { - protected array $data = []; + protected array $data = []; - public function __construct($message = '', $code = 0, array $data = [], Throwable $previous = null) - { - $this->data = $data; - parent::__construct($message, $code, $previous); - } + public function __construct($message = '', $code = 0, array $data = [], Throwable $previous = null) + { + $this->data = $data; + parent::__construct($message, $code, $previous); + } - public function getData(): array - { - return $this->data; - } + public function getData(): array + { + return $this->data; + } } diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index 2b59695..d629425 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -17,44 +17,44 @@ use Psr\Http\Message\ServerRequestInterface; abstract class ValidateEventAbstract implements ValidateEventInterface { - /** - * 当前验证场景 - * @var ?string - */ - protected ?string $sceneName; + /** + * 当前验证场景 + * @var ?string + */ + protected ?string $sceneName; - /** - * 场景验证前 - * @param array $data 用户输入的数据 - * @param ServerRequestInterface $request - * @param Closure $next - * @return mixed - */ - public function beforeValidate(array $data, ServerRequestInterface $request, Closure $next) - { - return $next($data, $request); - } - - /** - * 场景验证后 - * @param array $data 验证后的数据 - * @param ServerRequestInterface $request - * @param Closure $next - * @return mixed - */ - public function afterValidate(array $data, ServerRequestInterface $request, Closure $next) - { - return $next($data, $request); - } + /** + * 场景验证前 + * @param array $data 用户输入的数据 + * @param ServerRequestInterface $request + * @param Closure $next + * @return mixed + */ + public function beforeValidate(array $data, ServerRequestInterface $request, Closure $next) + { + return $next($data, $request); + } + + /** + * 场景验证后 + * @param array $data 验证后的数据 + * @param ServerRequestInterface $request + * @param Closure $next + * @return mixed + */ + public function afterValidate(array $data, ServerRequestInterface $request, Closure $next) + { + return $next($data, $request); + } - /** - * 写入当前的验证场景名称 - * @param string|null $sceneName - * @return $this - */ - final public function setSceneName(?string $sceneName): ValidateEventAbstract - { - $this->sceneName = $sceneName; - return $this; - } + /** + * 写入当前的验证场景名称 + * @param string|null $sceneName + * @return $this + */ + final public function setSceneName(?string $sceneName): ValidateEventAbstract + { + $this->sceneName = $sceneName; + return $this; + } } diff --git a/src/Support/Event/ValidateEventInterface.php b/src/Support/Event/ValidateEventInterface.php index c12e60e..6695351 100644 --- a/src/Support/Event/ValidateEventInterface.php +++ b/src/Support/Event/ValidateEventInterface.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -17,6 +17,6 @@ use Psr\Http\Message\ServerRequestInterface; interface ValidateEventInterface { - public function beforeValidate(array $data, ServerRequestInterface $request, Closure $next); - public function afterValidate(array $data, ServerRequestInterface $request, Closure $next); + public function beforeValidate(array $data, ServerRequestInterface $request, Closure $next); + public function afterValidate(array $data, ServerRequestInterface $request, Closure $next); } diff --git a/src/Support/Event/ValidateResult.php b/src/Support/Event/ValidateResult.php index a9db160..e38aa02 100644 --- a/src/Support/Event/ValidateResult.php +++ b/src/Support/Event/ValidateResult.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -16,23 +16,23 @@ use Psr\Http\Message\RequestInterface; class ValidateResult { - protected array $data; + protected array $data; - protected RequestInterface $request; - - public function __construct(array $data, RequestInterface $request) - { - $this->data = $data; - $this->request = $request; - } - - public function getData(): array - { - return $this->data; - } - - public function getRequest(): RequestInterface - { - return $this->request; - } + protected RequestInterface $request; + + public function __construct(array $data, RequestInterface $request) + { + $this->data = $data; + $this->request = $request; + } + + public function getData(): array + { + return $this->data; + } + + public function getRequest(): RequestInterface + { + return $this->request; + } } diff --git a/src/Support/Middleware/ValidateMiddleware.php b/src/Support/Middleware/ValidateMiddleware.php index 189705f..48b2da4 100644 --- a/src/Support/Middleware/ValidateMiddleware.php +++ b/src/Support/Middleware/ValidateMiddleware.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -25,92 +25,92 @@ use W7\Validate\Validate; class ValidateMiddleware extends MiddlewareAbstract { - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - { - $scene = null; - $validator = $this->getValidate($request); - if (false === $validator) { - $data = []; - } else { - $data = array_merge([], $request->getQueryParams(), $request->getParsedBody(), $request->getUploadedFiles()); - $data = $validator->check($data); - $request = $validator->getRequest(); - } + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + $scene = null; + $validator = $this->getValidate($request); + if (false === $validator) { + $data = []; + } else { + $data = array_merge([], $request->getQueryParams(), $request->getParsedBody(), $request->getUploadedFiles()); + $data = $validator->check($data); + $request = $validator->getRequest(); + } - /** @var Request $request */ - $request = $request->withAttribute('validate', $data); - Context::setRequest($request); - return $handler->handle($request); - } + /** @var Request $request */ + $request = $request->withAttribute('validate', $data); + Context::setRequest($request); + return $handler->handle($request); + } - final public function getValidate(ServerRequestInterface $request) - { - /** @var Route $route */ - $route = $request->getAttribute('route'); - $handler = $route->handler; - if (!is_array($handler) || 2 !== count($handler)) { - return false; - } - $controller = $handler[0] ?? ''; - $scene = $handler[1] ?? ''; - $haveLink = false; - $validate = ''; + final public function getValidate(ServerRequestInterface $request) + { + /** @var Route $route */ + $route = $request->getAttribute('route'); + $handler = $route->handler; + if (!is_array($handler) || 2 !== count($handler)) { + return false; + } + $controller = $handler[0] ?? ''; + $scene = $handler[1] ?? ''; + $haveLink = false; + $validate = ''; - $validateLink = ValidateConfig::instance()->getValidateLink($controller); - if (!empty($validateLink)) { - # 为指定的控制器方法指定了验证器 - if (isset($validateLink[$scene]) || isset($validateLink['!__other__'])) { - if (isset($validateLink['!__other__'])) { - $method = '!__other__'; - } else { - $method = $scene; - } + $validateLink = ValidateConfig::instance()->getValidateLink($controller); + if (!empty($validateLink)) { + # 为指定的控制器方法指定了验证器 + if (isset($validateLink[$scene]) || isset($validateLink['!__other__'])) { + if (isset($validateLink['!__other__'])) { + $method = '!__other__'; + } else { + $method = $scene; + } - # 为指定的验证器指定了验证场景 - if (is_array($validateLink[$method])) { - if (count($validateLink[$method]) >= 2) { - $validate = $validateLink[$method][0]; - $scene = $validateLink[$method][1]; - $haveLink = true; - } - } else { - $validate = $validateLink[$method]; - $haveLink = true; - } - } - } + # 为指定的验证器指定了验证场景 + if (is_array($validateLink[$method])) { + if (count($validateLink[$method]) >= 2) { + $validate = $validateLink[$method][0]; + $scene = $validateLink[$method][1]; + $haveLink = true; + } + } else { + $validate = $validateLink[$method]; + $haveLink = true; + } + } + } - if (false === $haveLink) { - # 处理指定了路径的控制器 - $controllerPath = ''; - $validatePath = ''; - foreach (ValidateConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { - if (false !== strpos($controller, $_controllerPath)) { - $controllerPath = $_controllerPath; - $validatePath = $_validatePath; - break; - } - } - if (empty($controllerPath)) { - return false; - } + if (false === $haveLink) { + # 处理指定了路径的控制器 + $controllerPath = ''; + $validatePath = ''; + foreach (ValidateConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { + if (false !== strpos($controller, $_controllerPath)) { + $controllerPath = $_controllerPath; + $validatePath = $_validatePath; + break; + } + } + if (empty($controllerPath)) { + return false; + } - $validate = str_replace($controllerPath, '', $controller); - $_namespace = explode('\\', $validate); - $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); - $validate = $validatePath . implode('\\', $_namespace) . '\\' . $fileName; - } + $validate = str_replace($controllerPath, '', $controller); + $_namespace = explode('\\', $validate); + $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); + $validate = $validatePath . implode('\\', $_namespace) . '\\' . $fileName; + } - if (class_exists($validate)) { - if (is_subclass_of($validate, Validate::class)) { - /** @var Validate $validator */ - $validator = new $validate($request); - $validator->scene($scene); - return $validator; - } + if (class_exists($validate)) { + if (is_subclass_of($validate, Validate::class)) { + /** @var Validate $validator */ + $validator = new $validate($request); + $validator->scene($scene); + return $validator; + } - throw new Exception("The given 'Validate' " . $validate . ' has to be a subtype of W7\Validate\Validate'); - } - return false; - } + throw new Exception("The given 'Validate' " . $validate . ' has to be a subtype of W7\Validate\Validate'); + } + return false; + } } diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index 28292f1..b5abbbd 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -14,31 +14,31 @@ namespace W7\Validate\Support\Rule; abstract class BaseRule implements RuleInterface { - /** - * 错误消息,支持format字符串 - * @var string - */ - protected string $message = ''; + /** + * 错误消息,支持format字符串 + * @var string + */ + protected string $message = ''; - /** - * 用于format错误消息的参数 - * @var array - */ - protected array $messageParam = []; + /** + * 用于format错误消息的参数 + * @var array + */ + protected array $messageParam = []; - public function setMessage(string $message): BaseRule - { - $this->message = $message; - return $this; - } + public function setMessage(string $message): BaseRule + { + $this->message = $message; + return $this; + } - public function getMessage(): string - { - return vsprintf($this->message, $this->messageParam); - } + public function getMessage(): string + { + return vsprintf($this->message, $this->messageParam); + } - public function message(): string - { - return $this->getMessage(); - } + public function message(): string + { + return $this->getMessage(); + } } diff --git a/src/Support/Rule/RuleInterface.php b/src/Support/Rule/RuleInterface.php index efadc81..8f21517 100644 --- a/src/Support/Rule/RuleInterface.php +++ b/src/Support/Rule/RuleInterface.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -16,19 +16,19 @@ use Illuminate\Contracts\Validation\Rule; interface RuleInterface extends Rule { - /** - * Determine if the validation rule passes. - * - * @param string $attribute - * @param mixed $value - * @return bool - */ - public function passes($attribute, $value): bool; + /** + * Determine if the validation rule passes. + * + * @param string $attribute + * @param mixed $value + * @return bool + */ + public function passes($attribute, $value): bool; - /** - * Get the validation error message. - * - * @return string - */ - public function message(): string; + /** + * Get the validation error message. + * + * @return string + */ + public function message(): string; } diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 4039761..944c9b1 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -21,242 +21,242 @@ use W7\Validate\Exception\CollectionException; class ValidateCollection extends Collection { - private ?string $paramType; + private ?string $paramType; - /** - * 将下一次取出的值强制转为int类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function int(): ValidateCollection - { - $this->paramType = 'int'; - return $this; - } + /** + * 将下一次取出的值强制转为int类型 + * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

+ * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function int(): ValidateCollection + { + $this->paramType = 'int'; + return $this; + } - /** - * 将下一次取出的值强制转为float类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function float(): ValidateCollection - { - $this->paramType = 'float'; - return $this; - } + /** + * 将下一次取出的值强制转为float类型 + * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

+ * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function float(): ValidateCollection + { + $this->paramType = 'float'; + return $this; + } - /** - * 将下一次取出的值强制转为string类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function string(): ValidateCollection - { - $this->paramType = 'string'; - return $this; - } + /** + * 将下一次取出的值强制转为string类型 + * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

+ * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function string(): ValidateCollection + { + $this->paramType = 'string'; + return $this; + } - /** - * 将下一次取出的值强制转为array类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function array(): ValidateCollection - { - $this->paramType = 'array'; - return $this; - } + /** + * 将下一次取出的值强制转为array类型 + * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

+ * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function array(): ValidateCollection + { + $this->paramType = 'array'; + return $this; + } - /** - * 将下一次取出的值强制转为object类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function object(): ValidateCollection - { - $this->paramType = 'object'; - return $this; - } + /** + * 将下一次取出的值强制转为object类型 + * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

+ * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function object(): ValidateCollection + { + $this->paramType = 'object'; + return $this; + } - /** - * 将下一次取出的值强制转为bool类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function bool(): ValidateCollection - { - $this->paramType = 'bool'; - return $this; - } + /** + * 将下一次取出的值强制转为bool类型 + * + * @see get 获取指定字段的值 + * @see pop 移除并返回集合的最后一个集合项 + * @see pull 移除并返回集合的第一个集合项 + * @see shift 移除并返回集合的第一个集合项 + * + *

此类型转换对上诉方法有效

+ * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 + * @return $this + */ + public function bool(): ValidateCollection + { + $this->paramType = 'bool'; + return $this; + } - /** - * 判断集合中是否存在指定的字段 - * @param mixed $key 要验证的字段 - * @return bool - */ - public function has($key): bool - { - $keys = is_array($key) ? $key : func_get_args(); - - foreach ($keys as $value) { - if (!Arr::has($this->items, $value)) { - return false; - } - } - - return true; - } + /** + * 判断集合中是否存在指定的字段 + * @param mixed $key 要验证的字段 + * @return bool + */ + public function has($key): bool + { + $keys = is_array($key) ? $key : func_get_args(); + + foreach ($keys as $value) { + if (!Arr::has($this->items, $value)) { + return false; + } + } + + return true; + } - /** - * 当指定字段存在时执行 - * @param mixed $key 要验证的字段 - * @param callable $callback 存在时执行 - * @param callable|null $default 不存在时执行 - * @return HigherOrderWhenProxy|mixed|ValidateCollection - */ - public function whenHas($key, callable $callback, callable $default = null) - { - return $this->when($this->has($key), $callback, $default); - } + /** + * 当指定字段存在时执行 + * @param mixed $key 要验证的字段 + * @param callable $callback 存在时执行 + * @param callable|null $default 不存在时执行 + * @return HigherOrderWhenProxy|mixed|ValidateCollection + */ + public function whenHas($key, callable $callback, callable $default = null) + { + return $this->when($this->has($key), $callback, $default); + } - /** - * 当指定字段不存在时执行 - * @param mixed $key 要验证的字段 - * @param callable $callback 不存在时执行 - * @param callable|null $default 存在时执行 - * @return HigherOrderWhenProxy|mixed|ValidateCollection - */ - public function whenNotHas($key, callable $callback, callable $default = null) - { - return $this->when(!$this->has($key), $callback, $default); - } + /** + * 当指定字段不存在时执行 + * @param mixed $key 要验证的字段 + * @param callable $callback 不存在时执行 + * @param callable|null $default 存在时执行 + * @return HigherOrderWhenProxy|mixed|ValidateCollection + */ + public function whenNotHas($key, callable $callback, callable $default = null) + { + return $this->when(!$this->has($key), $callback, $default); + } - /** - * 获取指定字段的值 - * @param mixed $key 字段名称 - * @param null $default 默认值 - * @return array|ArrayAccess|mixed - * @throws CollectionException - */ - public function get($key, $default = null) - { - if (false !== strpos($key, '.')) { - $value = Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); - } else { - $value = parent::get($key, $default); - } + /** + * 获取指定字段的值 + * @param mixed $key 字段名称 + * @param null $default 默认值 + * @return array|ArrayAccess|mixed + * @throws CollectionException + */ + public function get($key, $default = null) + { + if (false !== strpos($key, '.')) { + $value = Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); + } else { + $value = parent::get($key, $default); + } - return $this->typeConversion($value); - } + return $this->typeConversion($value); + } - /** - * 移除并返回集合的最后一个集合项 - * @return mixed - * @throws CollectionException - */ - public function pop() - { - return $this->typeConversion(parent::pop()); - } + /** + * 移除并返回集合的最后一个集合项 + * @return mixed + * @throws CollectionException + */ + public function pop() + { + return $this->typeConversion(parent::pop()); + } - /** - * 移除并返回集合的第一个集合项 - * @return mixed - * @throws CollectionException - */ - public function shift() - { - return $this->typeConversion(parent::shift()); - } + /** + * 移除并返回集合的第一个集合项 + * @return mixed + * @throws CollectionException + */ + public function shift() + { + return $this->typeConversion(parent::shift()); + } - /** - * 将指定键对应的值从集合中移除并返回 - * @param mixed $key 字段名称 - * @param null $default 默认值 - * @return mixed - * @throws CollectionException - */ - public function pull($key, $default = null) - { - $value = parent::pull($key, $default); - return $this->typeConversion($value); - } + /** + * 将指定键对应的值从集合中移除并返回 + * @param mixed $key 字段名称 + * @param null $default 默认值 + * @return mixed + * @throws CollectionException + */ + public function pull($key, $default = null) + { + $value = parent::pull($key, $default); + return $this->typeConversion($value); + } - /** - * 将值转为指定类型 - * @param $value - * @return mixed - * @throws CollectionException - */ - private function typeConversion($value) - { - if (!empty($this->paramType)) { - $error = null; - set_error_handler(function ($type, $msg) use (&$error) { - $error = $msg; - }); - settype($value, $this->paramType); - restore_error_handler(); - $this->paramType = null; - if (!empty($error)) { - throw new CollectionException($error); - } - } + /** + * 将值转为指定类型 + * @param $value + * @return mixed + * @throws CollectionException + */ + private function typeConversion($value) + { + if (!empty($this->paramType)) { + $error = null; + set_error_handler(function ($type, $msg) use (&$error) { + $error = $msg; + }); + settype($value, $this->paramType); + restore_error_handler(); + $this->paramType = null; + if (!empty($error)) { + throw new CollectionException($error); + } + } - return $value; - } + return $value; + } - /** - * 在集合中写入指定的值 - * @param mixed $key 要写入的字段 - * @param mixed $value 要写入的值 - * @return $this - */ - public function set($key, $value): ValidateCollection - { - Arr::set($this->items, $key, $value); - return $this; - } + /** + * 在集合中写入指定的值 + * @param mixed $key 要写入的字段 + * @param mixed $value 要写入的值 + * @return $this + */ + public function set($key, $value): ValidateCollection + { + Arr::set($this->items, $key, $value); + return $this; + } } diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 73cc57d..2c8cd9a 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -16,120 +16,120 @@ use W7\Core\Helper\Traiter\InstanceTraiter; class ValidateConfig { - use InstanceTraiter; - - /** - * 自定义规则命名空间前缀 - * @var array - */ - protected array $rulesPath = []; + use InstanceTraiter; + + /** + * 自定义规则命名空间前缀 + * @var array + */ + protected array $rulesPath = []; - /** - * 自动加载验证器规则 - * @var array - */ - protected array $autoValidatePath = []; + /** + * 自动加载验证器规则 + * @var array + */ + protected array $autoValidatePath = []; - /** - * 验证器具体关联 - * @var array - */ - protected array $validateLink = []; + /** + * 验证器具体关联 + * @var array + */ + protected array $validateLink = []; - /** - * 设置自动加载验证器规则 - * @param string $controllerPath 控制器路径 - * @param string $validatePath 验证器路径 - * @return $this - */ - public function setAutoValidatePath(string $controllerPath, string $validatePath): ValidateConfig - { - $this->autoValidatePath[$controllerPath] = $validatePath; - return $this; - } + /** + * 设置自动加载验证器规则 + * @param string $controllerPath 控制器路径 + * @param string $validatePath 验证器路径 + * @return $this + */ + public function setAutoValidatePath(string $controllerPath, string $validatePath): ValidateConfig + { + $this->autoValidatePath[$controllerPath] = $validatePath; + return $this; + } - /** - * 设置验证器关联 - * @param string|string[] $controller

控制器完整命名空间

- * 如需指定方法,请传数组,第二个元素为方法名 - * @param string|string[] $validate

验证器完整命名空间

- * 如需指定场景,请传数组,第二个元素为场景名 - * @return $this - */ - public function setValidateLink($controller, $validate): ValidateConfig - { - if (is_array($controller)) { - $controllers = $controller; - $controller = $controllers[0]; - $method = $controllers[1]; - # 数组中不可以存在 “\” 符号 - $controller = md5($controller); - if (count($controllers) >= 2) { - if (isset($this->validateLink[$controller])) { - $_validate = $this->validateLink[$controller]; - $_validate = array_merge($_validate, [ - $method => $validate - ]); - $this->validateLink[$controller] = $_validate; - } else { - $this->validateLink[$controller] = [ - $method => $validate - ]; - } - } - } else { - $controller = md5($controller); - if (isset($this->validateLink[$controller])) { - $this->validateLink[$controller]['!__other__'] = $validate; - } else { - $this->validateLink[$controller] = [ - '!__other__' => $validate - ]; - } - } - return $this; - } + /** + * 设置验证器关联 + * @param string|string[] $controller

控制器完整命名空间

+ * 如需指定方法,请传数组,第二个元素为方法名 + * @param string|string[] $validate

验证器完整命名空间

+ * 如需指定场景,请传数组,第二个元素为场景名 + * @return $this + */ + public function setValidateLink($controller, $validate): ValidateConfig + { + if (is_array($controller)) { + $controllers = $controller; + $controller = $controllers[0]; + $method = $controllers[1]; + # 数组中不可以存在 “\” 符号 + $controller = md5($controller); + if (count($controllers) >= 2) { + if (isset($this->validateLink[$controller])) { + $_validate = $this->validateLink[$controller]; + $_validate = array_merge($_validate, [ + $method => $validate + ]); + $this->validateLink[$controller] = $_validate; + } else { + $this->validateLink[$controller] = [ + $method => $validate + ]; + } + } + } else { + $controller = md5($controller); + if (isset($this->validateLink[$controller])) { + $this->validateLink[$controller]['!__other__'] = $validate; + } else { + $this->validateLink[$controller] = [ + '!__other__' => $validate + ]; + } + } + return $this; + } - /** - * 获取验证器具体关联 - * @param string|null $controller 验证器完整命名空间 - * @return array - */ - public function getValidateLink(?string $controller = null): array - { - if (null === $controller) { - return $this->validateLink; - } - return $this->validateLink[md5($controller)] ?? []; - } + /** + * 获取验证器具体关联 + * @param string|null $controller 验证器完整命名空间 + * @return array + */ + public function getValidateLink(?string $controller = null): array + { + if (null === $controller) { + return $this->validateLink; + } + return $this->validateLink[md5($controller)] ?? []; + } - /** - * 设置自定义规则命名空间前缀,如设置多个则全部生效 - * @param string $rulesPath 自定义规则命名空间前缀 - * @return $this - */ - public function setRulesPath(string $rulesPath): ValidateConfig - { - $this->rulesPath[] = $rulesPath; - $this->rulesPath = array_unique($this->rulesPath); - return $this; - } + /** + * 设置自定义规则命名空间前缀,如设置多个则全部生效 + * @param string $rulesPath 自定义规则命名空间前缀 + * @return $this + */ + public function setRulesPath(string $rulesPath): ValidateConfig + { + $this->rulesPath[] = $rulesPath; + $this->rulesPath = array_unique($this->rulesPath); + return $this; + } - /** - * 获取自定义规则命名空间前缀 - * @return array - */ - public function getRulePath(): array - { - return $this->rulesPath; - } + /** + * 获取自定义规则命名空间前缀 + * @return array + */ + public function getRulePath(): array + { + return $this->rulesPath; + } - /** - * 获取自动加载验证器规则 - * @return array - */ - public function getAutoValidatePath(): array - { - return $this->autoValidatePath; - } + /** + * 获取自动加载验证器规则 + * @return array + */ + public function getAutoValidatePath(): array + { + return $this->autoValidatePath; + } } diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index 51b468e..558329c 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -20,66 +20,66 @@ use W7\Validate\Support\Event\ValidateResult; class ValidateHandler { - protected array $handlers = []; + protected array $handlers = []; - protected array $data = []; + protected array $data = []; - protected RequestInterface $request; + protected RequestInterface $request; - protected ?string $sceneName = null; + protected ?string $sceneName = null; - public function __construct(array $data, array $handlers, RequestInterface $request, string $sceneName = null) - { - $this->data = $data; - $this->request = $request; - $this->handlers = $handlers; - $this->sceneName = $sceneName; - } - - protected function carry(): Closure - { - return function ($stack, $pipe) { - return function ($data, $request) use ($stack, $pipe) { - return $pipe($data, $request, $stack); - }; - }; - } - - protected function pipes(string $method): array - { - return array_map(function ($middleware) use ($method) { - return function ($data, $request, $next) use ($middleware, $method) { - list($callback, $param) = $middleware; - if (class_exists($callback) && is_subclass_of($callback, ValidateEventAbstract::class)) { - /** @var ValidateEventAbstract $handler */ - $handler = new $callback(...$param); - $handler->setSceneName($this->sceneName); - return call_user_func([$handler, $method], $data, $request, $next); - } else { - throw new ValidateException('Event error or nonexistence'); - } - }; - }, $this->handlers); - } - - protected function destination(): Closure - { - return function ($data, $request) { - return new ValidateResult($data, $request); - }; - } - - public function handle(string $method) - { - $destination = $this->destination(); - $pipeline = array_reduce( - array_reverse($this->pipes($method)), - $this->carry(), - function ($data, $request) use ($destination) { - return $destination($data, $request); - } - ); - - return $pipeline($this->data, $this->request); - } + public function __construct(array $data, array $handlers, RequestInterface $request, string $sceneName = null) + { + $this->data = $data; + $this->request = $request; + $this->handlers = $handlers; + $this->sceneName = $sceneName; + } + + protected function carry(): Closure + { + return function ($stack, $pipe) { + return function ($data, $request) use ($stack, $pipe) { + return $pipe($data, $request, $stack); + }; + }; + } + + protected function pipes(string $method): array + { + return array_map(function ($middleware) use ($method) { + return function ($data, $request, $next) use ($middleware, $method) { + list($callback, $param) = $middleware; + if (class_exists($callback) && is_subclass_of($callback, ValidateEventAbstract::class)) { + /** @var ValidateEventAbstract $handler */ + $handler = new $callback(...$param); + $handler->setSceneName($this->sceneName); + return call_user_func([$handler, $method], $data, $request, $next); + } else { + throw new ValidateException('Event error or nonexistence'); + } + }; + }, $this->handlers); + } + + protected function destination(): Closure + { + return function ($data, $request) { + return new ValidateResult($data, $request); + }; + } + + public function handle(string $method) + { + $destination = $this->destination(); + $pipeline = array_reduce( + array_reverse($this->pipes($method)), + $this->carry(), + function ($data, $request) use ($destination) { + return $destination($data, $request); + } + ); + + return $pipeline($this->data, $this->request); + } } diff --git a/src/Support/helpers.php b/src/Support/helpers.php index c27bd3e..89c73d4 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -15,28 +15,28 @@ use W7\Facade\Context; use W7\Validate\Support\Storage\ValidateCollection; if (!function_exists('validate_collect')) { - /** - * 数值转为验证器集合ValidateCollection类型 - * @param null $value - * @return ValidateCollection - */ - function validate_collect($value = null): ValidateCollection - { - return new ValidateCollection($value); - } + /** + * 数值转为验证器集合ValidateCollection类型 + * @param null $value + * @return ValidateCollection + */ + function validate_collect($value = null): ValidateCollection + { + return new ValidateCollection($value); + } } if (!function_exists('get_validate_data')) { - /** - * 获取验证后的结果 - * @param ServerRequestInterface|null $request 请求示例,如果为null,则自动从上下文中获取 - * @return ValidateCollection 返回验证器集合ValidateCollection类型 - */ - function get_validate_data(ServerRequestInterface $request = null): ValidateCollection - { - if (null === $request) { - $request = Context::getRequest(); - } - return validate_collect($request->getAttribute('validate')); - } + /** + * 获取验证后的结果 + * @param ServerRequestInterface|null $request 请求示例,如果为null,则自动从上下文中获取 + * @return ValidateCollection 返回验证器集合ValidateCollection类型 + */ + function get_validate_data(ServerRequestInterface $request = null): ValidateCollection + { + if (null === $request) { + $request = Context::getRequest(); + } + return validate_collect($request->getAttribute('validate')); + } } diff --git a/src/Validate.php b/src/Validate.php index ceb0429..d734393 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -29,656 +29,656 @@ use W7\Validate\Support\Storage\ValidateHandler; class Validate { - /** - * 自定义错误消息 - * @var array - */ - protected array $message = []; - - /** - * 验证规则 - * @var array - */ - protected array $rule = []; - - /** - * 验证场景数据,key为控制器内的方法 - * @var array - */ - protected array $scene = []; - - /** - * 全局事件处理器 - * @var array - */ - protected array $handler = []; - - /** - * 字段名称 - * @var array - */ - protected array $customAttributes = []; - - /** - * 是否首次验证失败后停止运行 - * @var bool - */ - protected bool $bail = true; - - /** - * 所有验证的字段在存在时不能为空,规则中带nullable除外 - * @var bool - */ - protected bool $filled = true; - - /** - * 当前验证场景 - * @var ?string - */ - private ?string $currentScene = null; - - /** - * 验证的规则 - * @var Collection - */ - private Collection $checkRule; - - /** - * 扩展方法名 - * @var array - */ - private static array $extendName = []; - - /** - * 验证器事件处理类 - * @var array - */ - private array $handlers = []; - - /** - * Request请求实例 - * @var RequestInterface|null - */ - protected ?RequestInterface $request = null; - - /** - * 当前进行验证的数据 - * @var array - */ - protected array $checkData = []; - - public function __construct(?RequestInterface $request = null) - { - $this->request = $request; - } - - /** - * 自动验证 - * @param array $data 待验证的数据 - * @return array - * @throws ValidateException - */ - public function check(array $data): array - { - try { - $this->checkData = $data; - $rule = $this->getSceneRules(); - if ($this->bail) { - $rule = $this->addBailRule($rule); - } - if ($this->filled){ - $rule = $this->addFilledRule($rule); - } - $data = $this->handleEvent($data, 'beforeValidate'); - /** @var \Illuminate\Validation\Validator $v */ - $v = Validator::make($data, $rule, $this->message, $this->customAttributes); - $data = $this->handleEvent($v->validate(), 'afterValidate'); - return $data; - } catch (ValidationException $e) { - $errors = $e->errors(); - $errorMessage = ''; - foreach ($errors as $field => $message) { - $errorMessage = $message[0]; - break; - } - - throw new ValidateException($errorMessage, 403, $errors); - } - } - - /** - * 验证事件处理 - * @param array $data 验证的数据 - * @param string $method 事件名称 - * @return array - * @throws ValidateException - */ - private function handleEvent(array $data, string $method): array - { - if (empty($this->handlers)) { - return $data; - } - $request = $this->request ?: Context::getRequest(); - $request ??= new Request('', null); - $result = (new ValidateHandler($data, $this->handlers, $request, $this->currentScene))->handle($method); - if (is_string($result)) { - throw new ValidateException($result, 403); - } elseif ($result instanceof ValidateResult) { - $this->request = $result->getRequest(); - return $result->getData(); - } - - throw new LogicException('Validate event return type error'); - } - - /** - * 获取请求类 - * @return RequestInterface|null - */ - public function getRequest(): ?RequestInterface - { - return $this->request; - } - - /** - * 初始化验证 - */ - private function init() - { - $this->checkRule = collect([]); - $this->handlers = []; - } - - /** - * 获取当前场景下需要验证的规则 - * @return array - * @throws ValidateException - */ - private function getSceneRules(): array - { - $this->init(); - $this->addHandler($this->handler); - $this->getScene($this->currentScene); - $this->checkRule->transform(function ($rule, $field) { - if (!is_array($rule) && !$rule instanceof Collection) { - $_rules = collect(explode('|', $rule)); - } else { - $_rules = collect($rule); - } - $_rules->transform(function ($value) use ($field) { - if (is_string($value)) { - # 判断是否为自定义规则 - $ruleClass = $this->getRuleClass($value); - if (false !== $ruleClass) { - # 给自定义规则设置自定义错误消息 - $message = $this->getMessages($field, $value); - if ($message) { - $ruleClass->setMessage($message); - } - return $ruleClass; - } - return $this->getExtendsName($value, $field); - } - return $value; - }); - return $_rules; - }); - return $this->checkRule->toArray(); - } - - /** - * 获取扩展方法的名称 - * 由于为了区分多个验证器的相同自定义方法名,对方法名做了处理,此方法为了使规则和处理后的方法名对应上 - * @param string $rule 规则名称 - * @param string|null $field 字段 - * @return string - */ - private function getExtendsName(string $rule, string $field = null): string - { - list($rule, $param) = $this->getKeyAndParam($rule, false); - - # 取回真实的自定义规则方法名称,以及修改对应的错误消息 - if (in_array($rule, self::$extendName)) { - $ruleName = md5(get_called_class() . $rule); - # 判断是否为自定义规则方法定义了错误消息 - if (null !== $field && isset($this->message[$field . '.' . $rule])) { - $this->message[$ruleName] = $this->message[$field . '.' . $rule]; - } - - $rule = $ruleName; - } - - if ('' !== $param) { - $rule = $rule . ':' . $param; - } - return $rule; - } - - /** - * 获取规则的名称和参数 - * @param string $value 规则 - * @param bool $parsing 是否解析参数,默认为false - * @return array - */ - private function getKeyAndParam(string $value, bool $parsing = false): array - { - $param = ''; - if (false !== strpos($value, ':')) { - $arg = explode(':', $value, 2); - $key = $arg[0]; - if (count($arg) >= 2) { - $param = $arg[1]; - } - } else { - $key = $value; - } - - if ($parsing) { - $param = explode(',', $param); - } - return [$key, $param]; - } - - /** - * 生成错误消息的名称 - * @param string $field 字段 - * @param string $rule 规则 - * @return string - */ - private function makeMessageName(string $field, string $rule): string - { - if (false !== strpos($rule, ':')) { - $rule = substr($rule, 0, strpos($rule, ':')); - } - return $field . '.' . $rule; - } - - /** - * 添加事件 - * @param $handlers - */ - private function addHandler($handlers) - { - if (is_string($handlers)) { - $this->handlers[] = [$handlers, []]; - } else { - foreach ($handlers as $handlerClass => $param) { - if (is_int($handlerClass)) { - $this->handlers[] = [$param, []]; - } elseif (is_string($handlerClass)) { - if (is_array($param)) { - $this->handler($handlerClass, ...$param); - } else { - $this->handler($handlerClass, $param); - } - } - } - } - } - - /** - * 添加bail规则 - * @param array $rules 原规则 - * @return array - */ - private function addBailRule(array $rules): array - { - foreach ($rules as $key => $rule) { - if (!in_array('bail', $rule)) { - array_unshift($rule, 'bail'); - $rules[$key] = $rule; - } - } - - return $rules; - } - - /** - * 添加filled规则 - * @param array $rules 原规则 - * @return array - */ - public function addFilledRule(array $rules): array - { - foreach ($rules as $key => $rule) { - if (!in_array('filled', $rule) && !in_array('nullable', $rule)) { - array_unshift($rule, 'filled'); - $rules[$key] = $rule; - } - } - - return $rules; - } - - /** - * 进入场景 - * @param string|null $name 场景名称 - * @return Validate - * @throws ValidateException - */ - private function getScene(?string $name = null): Validate - { - if (empty($name)) { - $this->checkRule = collect($this->rule); - return $this; - } - # 判断自定义验证场景是否存在 - if (method_exists($this, 'scene' . ucfirst($name))) { - $this->checkRule = collect($this->rule); - call_user_func([$this, 'scene' . ucfirst($name)]); - } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 - $sceneRule = $this->scene[$name]; - - # 判断是否定义了事件 - if (isset($sceneRule['handler'])) { - $handlers = $sceneRule['handler']; - $this->addHandler($handlers); - unset($sceneRule['handler']); - unset($this->scene[$name]['handler']); - } - - # 判断验证场景是否指定了其他验证场景 - if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { - $use = $sceneRule['use']; - unset($sceneRule['use']); - unset($this->scene[$name]['use']); - # 如果指定的use是一个方法 - if (method_exists($this, 'use' . ucfirst($use))) { - # 进行预验证,将需要传给闭包的值按指定规则进行验证 - $data = []; - if (!empty($sceneRule)) { - $randScene = md5(rand(1, 1000000) . time()); - $data = (clone $this)->setScene( - [$randScene => $sceneRule] - )->scene($randScene)->check($this->checkData); - } - - $use = call_user_func([$this, 'use' . ucfirst($use)], $data); - if (is_array($use)) { - $this->checkRule = collect($this->rule)->only($use); - return $this; - } - } - $this->getScene($use); - } else { - $this->checkRule = collect($this->rule)->only($sceneRule); - } - } else { - # 如果验证场景找不到,则默认验证全部规则 - $this->checkRule = collect($this->rule); - } - - return $this; - } - - /** - * 获取自定义规则的实例类 - * - * @param string $ruleName 自定义规则名称 - * @return false|mixed|Closure - */ - private function getRuleClass(string $ruleName) - { - list($ruleName, $param) = $this->getKeyAndParam($ruleName, true); - - foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { - $ruleNameSpace = $rulesPath . ucfirst($ruleName); - if (class_exists($ruleNameSpace)) { - return new $ruleNameSpace(...$param); - } - } - - return false; - } - - /** - * 注册自定义验证方法 - * - * @param string $rule 规则名称 - * @param Closure|string $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator - * @param string|null $message 错误消息 - */ - public static function extend(string $rule, $extension, ?string $message = null) - { - array_push(self::$extendName, $rule); - self::$extendName = array_unique(self::$extendName); - - # 多个验证器使用了同样的rule会导致后面的方法无法生效 - # 故这里根据命名空间生成一个独一无二的rule名称 - $ruleName = md5(get_called_class() . $rule); - Validator::extend($ruleName, $extension, $message); - } - - /** - * 设置验证场景 - * - * @param string $name - * @return $this - */ - public function scene(string $name): Validate - { - $this->currentScene = $name; - return $this; - } - - /** - * 加入事件 - * - * @param string $handler 事件的完整类名,完整命名空间字符串或者加::class - * @param mixed ...$params 要传递给事件的参数 - * @return $this - */ - public function handler(string $handler, ...$params): Validate - { - $this->handlers[] = [$handler, $params]; - return $this; - } - - /** - * 指定需要验证的字段列表 - * - * @param array $fields 字段名 - * @return $this - */ - public function only(array $fields): Validate - { - $this->checkRule = $this->checkRule->only($fields); - return $this; - } - - /** - * 追加某个字段的验证规则 - * - * @param string $field 字段名 - * @param string $rule 验证规则 - * @return $this - */ - public function append(string $field, string $rule): Validate - { - if (isset($this->checkRule[$field])) { - if (is_array($this->checkRule[$field])) { - $this->checkRule[$field] = collect($this->checkRule[$field]); - } - - if ($this->checkRule[$field] instanceof Collection) { - $appendRule = explode('|', $rule); - $this->checkRule[$field] = $this->checkRule[$field]->concat($appendRule); - } else { - $this->checkRule[$field] = $this->checkRule[$field] . '|' . $rule; - } - } - - return $this; - } - - /** - * 移除某个字段的验证规则 - * - * @param string $field 字段名 - * @param string|null $rule 验证规则 null 移除所有规则 - * @return $this - */ - public function remove(string $field, ?string $rule = null): Validate - { - $removeRule = $rule; - if (is_string($rule) && false !== strpos($rule, '|')) { - $removeRule = explode('|', $rule); - } - - if (is_array($removeRule)) { - foreach ($removeRule as $rule) { - $this->remove($field, $rule); - } - } else { - if (isset($this->checkRule[$field])) { - if (null === $rule) { - $this->checkRule[$field] = []; - } else { - $rules = $this->checkRule[$field]; - if (is_string($rules)) { - $rules = explode('|', $rules); - $rules = collect($rules); - } - - if (false !== strpos($rule, ':')) { - $rule = substr($rule, 0, strpos($rule, ':')); - } - $rules = $rules->filter(function ($value) use ($rule) { - if (false !== strpos($value, ':')) { - $value = substr($value, 0, strpos($value, ':')); - } - return $value !== $rule; - }); - - $this->checkRule[$field] = $rules; - } - } - } - - return $this; - } - - /** - * 复杂条件验证 - * - * @param string|string[] $attribute 字段 - * @param string|array|BaseRule $rules 规则 - * @param callable $callback 回调方法,返回true获取具体规则生效 - * @return $this - */ - public function sometimes($attribute, $rules, callable $callback): Validate - { - $data = new Fluent($this->checkData); - $result = $callback($data); - if (false === $result) { - return $this; - } elseif (true === $result) { - $result = $rules; - } - - if (is_array($result)) { - $result = implode('|', $result); - } - - if (is_array($attribute)) { - foreach ($attribute as $filed) { - $this->append($filed, $result); - } - } else { - $this->append($attribute, $result); - } - - return $this; - } - - /** - * 获取验证规则 - * - * @param null $rule 验证字段 - * @return array|mixed|null - */ - public function getRules($rule = null) - { - if (null === $rule) { - return $this->rule; - } - - if (is_array($rule)) { - return collect($this->rule)->only($rule)->toArray(); - } else { - return $this->rule[$rule] ?? null; - } - } - - /** - * 设置验证规则(叠加) - * - * @param array|null $rules [字段 => 规则] 如果$rules为null,则清空全部验证规则 - * @return $this - */ - public function setRules(?array $rules = null): Validate - { - if (null === $rules) { - $this->rule = []; - } - $this->rule = array_merge($this->rule, $rules); - return $this; - } - /** - * 获取验证消息 - * - * @param null|string|string[] $key 完整消息Key值 - * @param string|null $rule 如果第一个值为字段名,则第二个值则为规则,否则请留空 - * @return array|mixed|null - */ - public function getMessages($key = null, ?string $rule = null) - { - if (null === $key) { - return $this->message; - } - - if (null !== $rule) { - $messageName = $this->makeMessageName($key, $rule); - } else { - $messageName = $key; - } - - if (is_array($messageName)) { - return collect($this->message)->only($messageName)->toArray(); - } else { - return $this->message[$messageName] ?? null; - } - } - - /** - * 设置错误消息(叠加) - * - * @param array|null $message [字段.规则 => 验证消息] 如果$message为null,则清空全部验证消息 - * @return $this - */ - public function setMessages(?array $message = null): Validate - { - if (null === $message) { - $this->message = []; - } - - $this->message = array_merge($this->message, $message); - return $this; - } - - /** - * 设置验证场景(叠加) - * - * @param array|null $scene [场景 => [字段]] 如果$scene为null,则清空全部验证场景 - * @return $this - */ - public function setScene(?array $scene = null): Validate - { - if (null === $scene) { - $this->scene = []; - } - - $this->scene = array_merge($this->scene, $scene); - return $this; - } + /** + * 自定义错误消息 + * @var array + */ + protected array $message = []; + + /** + * 验证规则 + * @var array + */ + protected array $rule = []; + + /** + * 验证场景数据,key为控制器内的方法 + * @var array + */ + protected array $scene = []; + + /** + * 全局事件处理器 + * @var array + */ + protected array $handler = []; + + /** + * 字段名称 + * @var array + */ + protected array $customAttributes = []; + + /** + * 是否首次验证失败后停止运行 + * @var bool + */ + protected bool $bail = true; + + /** + * 所有验证的字段在存在时不能为空,规则中带nullable除外 + * @var bool + */ + protected bool $filled = true; + + /** + * 当前验证场景 + * @var ?string + */ + private ?string $currentScene = null; + + /** + * 验证的规则 + * @var Collection + */ + private Collection $checkRule; + + /** + * 扩展方法名 + * @var array + */ + private static array $extendName = []; + + /** + * 验证器事件处理类 + * @var array + */ + private array $handlers = []; + + /** + * Request请求实例 + * @var RequestInterface|null + */ + protected ?RequestInterface $request = null; + + /** + * 当前进行验证的数据 + * @var array + */ + protected array $checkData = []; + + public function __construct(?RequestInterface $request = null) + { + $this->request = $request; + } + + /** + * 自动验证 + * @param array $data 待验证的数据 + * @return array + * @throws ValidateException + */ + public function check(array $data): array + { + try { + $this->checkData = $data; + $rule = $this->getSceneRules(); + if ($this->bail) { + $rule = $this->addBailRule($rule); + } + if ($this->filled) { + $rule = $this->addFilledRule($rule); + } + $data = $this->handleEvent($data, 'beforeValidate'); + /** @var \Illuminate\Validation\Validator $v */ + $v = Validator::make($data, $rule, $this->message, $this->customAttributes); + $data = $this->handleEvent($v->validate(), 'afterValidate'); + return $data; + } catch (ValidationException $e) { + $errors = $e->errors(); + $errorMessage = ''; + foreach ($errors as $field => $message) { + $errorMessage = $message[0]; + break; + } + + throw new ValidateException($errorMessage, 403, $errors); + } + } + + /** + * 验证事件处理 + * @param array $data 验证的数据 + * @param string $method 事件名称 + * @return array + * @throws ValidateException + */ + private function handleEvent(array $data, string $method): array + { + if (empty($this->handlers)) { + return $data; + } + $request = $this->request ?: Context::getRequest(); + $request ??= new Request('', null); + $result = (new ValidateHandler($data, $this->handlers, $request, $this->currentScene))->handle($method); + if (is_string($result)) { + throw new ValidateException($result, 403); + } elseif ($result instanceof ValidateResult) { + $this->request = $result->getRequest(); + return $result->getData(); + } + + throw new LogicException('Validate event return type error'); + } + + /** + * 获取请求类 + * @return RequestInterface|null + */ + public function getRequest(): ?RequestInterface + { + return $this->request; + } + + /** + * 初始化验证 + */ + private function init() + { + $this->checkRule = collect([]); + $this->handlers = []; + } + + /** + * 获取当前场景下需要验证的规则 + * @return array + * @throws ValidateException + */ + private function getSceneRules(): array + { + $this->init(); + $this->addHandler($this->handler); + $this->getScene($this->currentScene); + $this->checkRule->transform(function ($rule, $field) { + if (!is_array($rule) && !$rule instanceof Collection) { + $_rules = collect(explode('|', $rule)); + } else { + $_rules = collect($rule); + } + $_rules->transform(function ($value) use ($field) { + if (is_string($value)) { + # 判断是否为自定义规则 + $ruleClass = $this->getRuleClass($value); + if (false !== $ruleClass) { + # 给自定义规则设置自定义错误消息 + $message = $this->getMessages($field, $value); + if ($message) { + $ruleClass->setMessage($message); + } + return $ruleClass; + } + return $this->getExtendsName($value, $field); + } + return $value; + }); + return $_rules; + }); + return $this->checkRule->toArray(); + } + + /** + * 获取扩展方法的名称 + * 由于为了区分多个验证器的相同自定义方法名,对方法名做了处理,此方法为了使规则和处理后的方法名对应上 + * @param string $rule 规则名称 + * @param string|null $field 字段 + * @return string + */ + private function getExtendsName(string $rule, string $field = null): string + { + list($rule, $param) = $this->getKeyAndParam($rule, false); + + # 取回真实的自定义规则方法名称,以及修改对应的错误消息 + if (in_array($rule, self::$extendName)) { + $ruleName = md5(get_called_class() . $rule); + # 判断是否为自定义规则方法定义了错误消息 + if (null !== $field && isset($this->message[$field . '.' . $rule])) { + $this->message[$ruleName] = $this->message[$field . '.' . $rule]; + } + + $rule = $ruleName; + } + + if ('' !== $param) { + $rule = $rule . ':' . $param; + } + return $rule; + } + + /** + * 获取规则的名称和参数 + * @param string $value 规则 + * @param bool $parsing 是否解析参数,默认为false + * @return array + */ + private function getKeyAndParam(string $value, bool $parsing = false): array + { + $param = ''; + if (false !== strpos($value, ':')) { + $arg = explode(':', $value, 2); + $key = $arg[0]; + if (count($arg) >= 2) { + $param = $arg[1]; + } + } else { + $key = $value; + } + + if ($parsing) { + $param = explode(',', $param); + } + return [$key, $param]; + } + + /** + * 生成错误消息的名称 + * @param string $field 字段 + * @param string $rule 规则 + * @return string + */ + private function makeMessageName(string $field, string $rule): string + { + if (false !== strpos($rule, ':')) { + $rule = substr($rule, 0, strpos($rule, ':')); + } + return $field . '.' . $rule; + } + + /** + * 添加事件 + * @param $handlers + */ + private function addHandler($handlers) + { + if (is_string($handlers)) { + $this->handlers[] = [$handlers, []]; + } else { + foreach ($handlers as $handlerClass => $param) { + if (is_int($handlerClass)) { + $this->handlers[] = [$param, []]; + } elseif (is_string($handlerClass)) { + if (is_array($param)) { + $this->handler($handlerClass, ...$param); + } else { + $this->handler($handlerClass, $param); + } + } + } + } + } + + /** + * 添加bail规则 + * @param array $rules 原规则 + * @return array + */ + private function addBailRule(array $rules): array + { + foreach ($rules as $key => $rule) { + if (!in_array('bail', $rule)) { + array_unshift($rule, 'bail'); + $rules[$key] = $rule; + } + } + + return $rules; + } + + /** + * 添加filled规则 + * @param array $rules 原规则 + * @return array + */ + public function addFilledRule(array $rules): array + { + foreach ($rules as $key => $rule) { + if (!in_array('filled', $rule) && !in_array('nullable', $rule)) { + array_unshift($rule, 'filled'); + $rules[$key] = $rule; + } + } + + return $rules; + } + + /** + * 进入场景 + * @param string|null $name 场景名称 + * @return Validate + * @throws ValidateException + */ + private function getScene(?string $name = null): Validate + { + if (empty($name)) { + $this->checkRule = collect($this->rule); + return $this; + } + # 判断自定义验证场景是否存在 + if (method_exists($this, 'scene' . ucfirst($name))) { + $this->checkRule = collect($this->rule); + call_user_func([$this, 'scene' . ucfirst($name)]); + } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 + $sceneRule = $this->scene[$name]; + + # 判断是否定义了事件 + if (isset($sceneRule['handler'])) { + $handlers = $sceneRule['handler']; + $this->addHandler($handlers); + unset($sceneRule['handler']); + unset($this->scene[$name]['handler']); + } + + # 判断验证场景是否指定了其他验证场景 + if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { + $use = $sceneRule['use']; + unset($sceneRule['use']); + unset($this->scene[$name]['use']); + # 如果指定的use是一个方法 + if (method_exists($this, 'use' . ucfirst($use))) { + # 进行预验证,将需要传给闭包的值按指定规则进行验证 + $data = []; + if (!empty($sceneRule)) { + $randScene = md5(rand(1, 1000000) . time()); + $data = (clone $this)->setScene( + [$randScene => $sceneRule] + )->scene($randScene)->check($this->checkData); + } + + $use = call_user_func([$this, 'use' . ucfirst($use)], $data); + if (is_array($use)) { + $this->checkRule = collect($this->rule)->only($use); + return $this; + } + } + $this->getScene($use); + } else { + $this->checkRule = collect($this->rule)->only($sceneRule); + } + } else { + # 如果验证场景找不到,则默认验证全部规则 + $this->checkRule = collect($this->rule); + } + + return $this; + } + + /** + * 获取自定义规则的实例类 + * + * @param string $ruleName 自定义规则名称 + * @return false|mixed|Closure + */ + private function getRuleClass(string $ruleName) + { + list($ruleName, $param) = $this->getKeyAndParam($ruleName, true); + + foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { + $ruleNameSpace = $rulesPath . ucfirst($ruleName); + if (class_exists($ruleNameSpace)) { + return new $ruleNameSpace(...$param); + } + } + + return false; + } + + /** + * 注册自定义验证方法 + * + * @param string $rule 规则名称 + * @param Closure|string $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator + * @param string|null $message 错误消息 + */ + public static function extend(string $rule, $extension, ?string $message = null) + { + array_push(self::$extendName, $rule); + self::$extendName = array_unique(self::$extendName); + + # 多个验证器使用了同样的rule会导致后面的方法无法生效 + # 故这里根据命名空间生成一个独一无二的rule名称 + $ruleName = md5(get_called_class() . $rule); + Validator::extend($ruleName, $extension, $message); + } + + /** + * 设置验证场景 + * + * @param string $name + * @return $this + */ + public function scene(string $name): Validate + { + $this->currentScene = $name; + return $this; + } + + /** + * 加入事件 + * + * @param string $handler 事件的完整类名,完整命名空间字符串或者加::class + * @param mixed ...$params 要传递给事件的参数 + * @return $this + */ + public function handler(string $handler, ...$params): Validate + { + $this->handlers[] = [$handler, $params]; + return $this; + } + + /** + * 指定需要验证的字段列表 + * + * @param array $fields 字段名 + * @return $this + */ + public function only(array $fields): Validate + { + $this->checkRule = $this->checkRule->only($fields); + return $this; + } + + /** + * 追加某个字段的验证规则 + * + * @param string $field 字段名 + * @param string $rule 验证规则 + * @return $this + */ + public function append(string $field, string $rule): Validate + { + if (isset($this->checkRule[$field])) { + if (is_array($this->checkRule[$field])) { + $this->checkRule[$field] = collect($this->checkRule[$field]); + } + + if ($this->checkRule[$field] instanceof Collection) { + $appendRule = explode('|', $rule); + $this->checkRule[$field] = $this->checkRule[$field]->concat($appendRule); + } else { + $this->checkRule[$field] = $this->checkRule[$field] . '|' . $rule; + } + } + + return $this; + } + + /** + * 移除某个字段的验证规则 + * + * @param string $field 字段名 + * @param string|null $rule 验证规则 null 移除所有规则 + * @return $this + */ + public function remove(string $field, ?string $rule = null): Validate + { + $removeRule = $rule; + if (is_string($rule) && false !== strpos($rule, '|')) { + $removeRule = explode('|', $rule); + } + + if (is_array($removeRule)) { + foreach ($removeRule as $rule) { + $this->remove($field, $rule); + } + } else { + if (isset($this->checkRule[$field])) { + if (null === $rule) { + $this->checkRule[$field] = []; + } else { + $rules = $this->checkRule[$field]; + if (is_string($rules)) { + $rules = explode('|', $rules); + $rules = collect($rules); + } + + if (false !== strpos($rule, ':')) { + $rule = substr($rule, 0, strpos($rule, ':')); + } + $rules = $rules->filter(function ($value) use ($rule) { + if (false !== strpos($value, ':')) { + $value = substr($value, 0, strpos($value, ':')); + } + return $value !== $rule; + }); + + $this->checkRule[$field] = $rules; + } + } + } + + return $this; + } + + /** + * 复杂条件验证 + * + * @param string|string[] $attribute 字段 + * @param string|array|BaseRule $rules 规则 + * @param callable $callback 回调方法,返回true获取具体规则生效 + * @return $this + */ + public function sometimes($attribute, $rules, callable $callback): Validate + { + $data = new Fluent($this->checkData); + $result = $callback($data); + if (false === $result) { + return $this; + } elseif (true === $result) { + $result = $rules; + } + + if (is_array($result)) { + $result = implode('|', $result); + } + + if (is_array($attribute)) { + foreach ($attribute as $filed) { + $this->append($filed, $result); + } + } else { + $this->append($attribute, $result); + } + + return $this; + } + + /** + * 获取验证规则 + * + * @param null $rule 验证字段 + * @return array|mixed|null + */ + public function getRules($rule = null) + { + if (null === $rule) { + return $this->rule; + } + + if (is_array($rule)) { + return collect($this->rule)->only($rule)->toArray(); + } else { + return $this->rule[$rule] ?? null; + } + } + + /** + * 设置验证规则(叠加) + * + * @param array|null $rules [字段 => 规则] 如果$rules为null,则清空全部验证规则 + * @return $this + */ + public function setRules(?array $rules = null): Validate + { + if (null === $rules) { + $this->rule = []; + } + $this->rule = array_merge($this->rule, $rules); + return $this; + } + /** + * 获取验证消息 + * + * @param null|string|string[] $key 完整消息Key值 + * @param string|null $rule 如果第一个值为字段名,则第二个值则为规则,否则请留空 + * @return array|mixed|null + */ + public function getMessages($key = null, ?string $rule = null) + { + if (null === $key) { + return $this->message; + } + + if (null !== $rule) { + $messageName = $this->makeMessageName($key, $rule); + } else { + $messageName = $key; + } + + if (is_array($messageName)) { + return collect($this->message)->only($messageName)->toArray(); + } else { + return $this->message[$messageName] ?? null; + } + } + + /** + * 设置错误消息(叠加) + * + * @param array|null $message [字段.规则 => 验证消息] 如果$message为null,则清空全部验证消息 + * @return $this + */ + public function setMessages(?array $message = null): Validate + { + if (null === $message) { + $this->message = []; + } + + $this->message = array_merge($this->message, $message); + return $this; + } + + /** + * 设置验证场景(叠加) + * + * @param array|null $scene [场景 => [字段]] 如果$scene为null,则清空全部验证场景 + * @return $this + */ + public function setScene(?array $scene = null): Validate + { + if (null === $scene) { + $this->scene = []; + } + + $this->scene = array_merge($this->scene, $scene); + return $this; + } } diff --git a/tests/Material/Rules/AlphaNum.php b/tests/Material/Rules/AlphaNum.php index 2ecac95..f459f20 100644 --- a/tests/Material/Rules/AlphaNum.php +++ b/tests/Material/Rules/AlphaNum.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -16,10 +16,10 @@ use W7\Validate\Support\Rule\BaseRule; class AlphaNum extends BaseRule { - protected string $message = ':attribute的值只能具有英文字母,数字'; - - public function passes($attribute, $value): bool - { - return is_scalar($value) && 1 === preg_match('/^[A-Za-z0-9]+$/', (string)$value); - } + protected string $message = ':attribute的值只能具有英文字母,数字'; + + public function passes($attribute, $value): bool + { + return is_scalar($value) && 1 === preg_match('/^[A-Za-z0-9]+$/', (string)$value); + } } diff --git a/tests/Material/Rules/ChsAlphaNum.php b/tests/Material/Rules/ChsAlphaNum.php index ce252ea..365aee0 100644 --- a/tests/Material/Rules/ChsAlphaNum.php +++ b/tests/Material/Rules/ChsAlphaNum.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -16,10 +16,10 @@ use W7\Validate\Support\Rule\BaseRule; class ChsAlphaNum extends BaseRule { - protected string $message = ':attribute的值只能具有中文,字母,数字'; - - public function passes($attribute, $value): bool - { - return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u', (string)$value); - } + protected string $message = ':attribute的值只能具有中文,字母,数字'; + + public function passes($attribute, $value): bool + { + return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}a-zA-Z0-9]+$/u', (string)$value); + } } diff --git a/tests/Material/TestArticleValidate.php b/tests/Material/TestArticleValidate.php index dba6af1..1e6cbd7 100644 --- a/tests/Material/TestArticleValidate.php +++ b/tests/Material/TestArticleValidate.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -16,43 +16,43 @@ use W7\Validate\Validate; class TestArticleValidate extends Validate { - protected array $rule = [ - 'id' => 'required|numeric', - 'content' => 'required|between:1,2000', - 'title' => 'required|between:4,50|alpha', - 'type' => 'required|numeric', - ]; + protected array $rule = [ + 'id' => 'required|numeric', + 'content' => 'required|between:1,2000', + 'title' => 'required|between:4,50|alpha', + 'type' => 'required|numeric', + ]; - protected array $message = [ - 'id.required' => '缺少参数:文章Id', - 'id.numeric' => '参数错误:文章Id', - 'content.required' => '文章内容必须填写', - 'content.digits_between' => '文章长度为1~2000个字符', - 'title.required' => '文章标题必须填写', - 'title.digits_between' => '文章标题格式错误', - 'title.alpha' => '文章标题长度为4~50个字符', - 'type.required' => '文章分类必须填写', - 'type.numeric' => '文章分类错误', - ]; - - protected array $scene = [ - 'add' => ['content', 'title'], - 'save' => ['use' => 'edit'], - 'del' => ['id'], - ]; - - public function sceneEdit() - { - return $this->only(['id', 'content', 'title']) - ->append('id', 'max:10000') - ->remove('content', 'between') - ->remove('title', null) - ->append('title', 'required|between:4,50|alpha'); - } - - public function sceneDynamic() - { - return $this->only(['title', 'content']) - ->remove('content', 'between'); - } + protected array $message = [ + 'id.required' => '缺少参数:文章Id', + 'id.numeric' => '参数错误:文章Id', + 'content.required' => '文章内容必须填写', + 'content.digits_between' => '文章长度为1~2000个字符', + 'title.required' => '文章标题必须填写', + 'title.digits_between' => '文章标题格式错误', + 'title.alpha' => '文章标题长度为4~50个字符', + 'type.required' => '文章分类必须填写', + 'type.numeric' => '文章分类错误', + ]; + + protected array $scene = [ + 'add' => ['content', 'title'], + 'save' => ['use' => 'edit'], + 'del' => ['id'], + ]; + + public function sceneEdit() + { + return $this->only(['id', 'content', 'title']) + ->append('id', 'max:10000') + ->remove('content', 'between') + ->remove('title', null) + ->append('title', 'required|between:4,50|alpha'); + } + + public function sceneDynamic() + { + return $this->only(['title', 'content']) + ->remove('content', 'between'); + } } diff --git a/tests/Material/TestBaseValidate.php b/tests/Material/TestBaseValidate.php index 93f0795..bfe4c8b 100644 --- a/tests/Material/TestBaseValidate.php +++ b/tests/Material/TestBaseValidate.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -17,18 +17,18 @@ use W7\Validate\Support\Storage\ValidateConfig; class TestBaseValidate extends TestCase { - public function __construct($name = null, array $data = [], $dataName = '') - { - $this->rangineInit(); - ValidateConfig::instance()->setRulesPath('W7\\Tests\\Material\\Rules\\'); - - parent::__construct($name, $data, $dataName); - } - - private function rangineInit() - { - !defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 2)); - !defined('APP_PATH') && define('APP_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'app'); - !defined('RUNTIME_PATH') && define('RUNTIME_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'runtime'); - } + public function __construct($name = null, array $data = [], $dataName = '') + { + $this->rangineInit(); + ValidateConfig::instance()->setRulesPath('W7\\Tests\\Material\\Rules\\'); + + parent::__construct($name, $data, $dataName); + } + + private function rangineInit() + { + !defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 2)); + !defined('APP_PATH') && define('APP_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'app'); + !defined('RUNTIME_PATH') && define('RUNTIME_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'runtime'); + } } diff --git a/tests/TestValidateScene.php b/tests/TestValidateScene.php index 612d904..8498520 100644 --- a/tests/TestValidateScene.php +++ b/tests/TestValidateScene.php @@ -3,7 +3,7 @@ /** * WeEngine System * - * (c) We7Team 2019 + * (c) We7Team 2021 * * This is not a free software * Using it under the license terms @@ -18,68 +18,68 @@ use W7\Validate\Exception\ValidateException; class TestValidateScene extends TestBaseValidate { - protected array $userInput; + protected array $userInput; - public function __construct($name = null, array $data = [], $dataName = '') - { - parent::__construct($name, $data, $dataName); - $this->userInput = [ - 'content' => '内容', - 'title' => '这是一个标题' - ]; - } + public function __construct($name = null, array $data = [], $dataName = '') + { + parent::__construct($name, $data, $dataName); + $this->userInput = [ + 'content' => '内容', + 'title' => '这是一个标题' + ]; + } - /** - * @test 测试没有指定验证场景的情况 - * @throws ValidateException - */ - public function testNotScene() - { - $v = new TestArticleValidate(); - $this->expectException(ValidateException::class); - $v->check($this->userInput); - } + /** + * @test 测试没有指定验证场景的情况 + * @throws ValidateException + */ + public function testNotScene() + { + $v = new TestArticleValidate(); + $this->expectException(ValidateException::class); + $v->check($this->userInput); + } - /** - * @test 测试制定验证场景 - * @throws ValidateException - */ - public function testScene() - { - $v = new TestArticleValidate(); - $data = $v->scene('add')->check($this->userInput); - $this->assertEquals('内容', $data['content']); - } - - /** - * @test 测试自定义验证场景 edit - * @throws ValidateException - */ - public function testCustomScene() - { - $validate = new TestArticleValidate(); - $this->expectException(ValidateException::class); - $validate->scene('edit')->check($this->userInput); - } - - /** - * @test 测试Use自定义验证场景 save - * @throws ValidateException - */ - public function testUseScene() - { - $validate = new TestArticleValidate(); - $this->expectExceptionMessage('缺少参数:文章Id'); - $validate->scene('save')->check($this->userInput); - } - - public function testDynamicScene() - { - $validate = new TestArticleValidate(); - $data = $validate->scene('dynamic')->check([ - 'title' => '标题标题标题标题', - 'content' => '1' - ]); - $this->assertEquals('1', $data['content']); - } + /** + * @test 测试制定验证场景 + * @throws ValidateException + */ + public function testScene() + { + $v = new TestArticleValidate(); + $data = $v->scene('add')->check($this->userInput); + $this->assertEquals('内容', $data['content']); + } + + /** + * @test 测试自定义验证场景 edit + * @throws ValidateException + */ + public function testCustomScene() + { + $validate = new TestArticleValidate(); + $this->expectException(ValidateException::class); + $validate->scene('edit')->check($this->userInput); + } + + /** + * @test 测试Use自定义验证场景 save + * @throws ValidateException + */ + public function testUseScene() + { + $validate = new TestArticleValidate(); + $this->expectExceptionMessage('缺少参数:文章Id'); + $validate->scene('save')->check($this->userInput); + } + + public function testDynamicScene() + { + $validate = new TestArticleValidate(); + $data = $validate->scene('dynamic')->check([ + 'title' => '标题标题标题标题', + 'content' => '1' + ]); + $this->assertEquals('1', $data['content']); + } } -- Gitee From c8cbf687d89028ed64a373691e48c2cc01130cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 9 Mar 2021 14:14:48 +0800 Subject: [PATCH 031/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=B6=88=E6=81=AF=E6=94=AF=E6=8C=81=E5=AF=B9=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E5=86=85=E5=AE=B9=E7=9A=84=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 在消息中添加{:field}则可以完成对检测内容的使用 --- src/Validate.php | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Validate.php b/src/Validate.php index d734393..fcd2529 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -13,6 +13,7 @@ namespace W7\Validate; use Closure; +use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Fluent; use Illuminate\Validation\ValidationException; @@ -135,7 +136,7 @@ class Validate $data = $this->handleEvent($v->validate(), 'afterValidate'); return $data; } catch (ValidationException $e) { - $errors = $e->errors(); + $errors = $this->handlingError($e->errors()); $errorMessage = ''; foreach ($errors as $field => $message) { $errorMessage = $message[0]; @@ -146,6 +147,38 @@ class Validate } } + /** + * 处理错误消息 + * @param array $errors + * @return array + */ + private function handlingError(array $errors): array + { + foreach ($errors as $field => &$errorMessages) { + if (is_array($errorMessages)) { + $errorMessages = array_map([$this, 'replacingFieldsInMessage'], $errorMessages); + } else { + $errorMessages = $this->replacingFieldsInMessage($errorMessages); + } + } + return $errors; + } + + /** + * 替换错误消息中的字段 + * @param string $message + * @return string|string[] + */ + private function replacingFieldsInMessage(string $message) + { + if (preg_match_all('/\{:(.*?)}/', $message, $matches) > 0) { + foreach ($matches[0] as $index => $pregString) { + $message = str_replace($pregString, Arr::get($this->checkData, $matches[1][$index], ''), $message); + } + } + return $message; + } + /** * 验证事件处理 * @param array $data 验证的数据 -- Gitee From 4b148b869b5feb0150f4f945f4a5c0c86cfaed3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 9 Mar 2021 16:01:04 +0800 Subject: [PATCH 032/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8Dsometimes?= =?UTF-8?q?=E4=BC=A0=E5=85=A5=E9=9D=9E=E6=9C=AC=E7=B1=BB=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9A=84=E6=97=B6=E5=80=99=EF=BC=8C=E5=AF=BC=E8=87=B4=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Validate.php b/src/Validate.php index fcd2529..641c65e 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -602,7 +602,7 @@ class Validate public function sometimes($attribute, $rules, callable $callback): Validate { $data = new Fluent($this->checkData); - $result = $callback($data); + $result = call_user_func($callback, $data); if (false === $result) { return $this; } elseif (true === $result) { -- Gitee From fde4a4852f4e75467aff310014a85a6267588a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 9 Mar 2021 18:20:49 +0800 Subject: [PATCH 033/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0replacer?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E5=90=8C=E6=97=B6=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?extend=E5=AF=B9=E9=9D=99=E6=80=81=E6=96=B9=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 641c65e..4221d64 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -271,7 +271,8 @@ class Validate list($rule, $param) = $this->getKeyAndParam($rule, false); # 取回真实的自定义规则方法名称,以及修改对应的错误消息 - if (in_array($rule, self::$extendName)) { + + if (array_key_exists($rule, self::$extendName)) { $ruleName = md5(get_called_class() . $rule); # 判断是否为自定义规则方法定义了错误消息 if (null !== $field && isset($this->message[$field . '.' . $rule])) { @@ -468,13 +469,18 @@ class Validate * 注册自定义验证方法 * * @param string $rule 规则名称 - * @param Closure|string $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator + * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator * @param string|null $message 错误消息 */ public static function extend(string $rule, $extension, ?string $message = null) { - array_push(self::$extendName, $rule); - self::$extendName = array_unique(self::$extendName); + $ruleName = md5(get_called_class() . $rule); + + if (array_key_exists($rule, self::$extendName)) { + array_push(self::$extendName[$rule], $ruleName); + } else { + self::$extendName[$rule] = [$ruleName]; + } # 多个验证器使用了同样的rule会导致后面的方法无法生效 # 故这里根据命名空间生成一个独一无二的rule名称 @@ -482,6 +488,22 @@ class Validate Validator::extend($ruleName, $extension, $message); } + /** + * 注册自定义验证方法错误消息 + * @param string $rule 规则名称 + * @param string|Closure $replacer 闭包规则,回调四个值 $message,$attribute,$rule,$parameters + */ + public static function replacer(string $rule, $replacer) + { + if (array_key_exists($rule, self::$extendName)) { + $ruleName = md5(get_called_class() . $rule); + if (in_array($ruleName, self::$extendName[$rule])) { + $rule = $ruleName; + } + } + Validator::replacer($rule, $replacer); + } + /** * 设置验证场景 * -- Gitee From 6863b8116ee84052742931233ebbe66e5818d815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 10 Mar 2021 11:04:39 +0800 Subject: [PATCH 034/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E7=94=B1?= =?UTF-8?q?=E4=BA=8Efilled=E8=A7=84=E5=88=99=E5=AF=BC=E8=87=B4=E7=9A=84pre?= =?UTF-8?q?sent=E8=A7=84=E5=88=99=E4=B8=8D=E7=94=9F=E6=95=88=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E8=A7=84=E5=88=99=E5=A4=9A=E4=BD=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 4221d64..adff207 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -374,8 +374,12 @@ class Validate */ public function addFilledRule(array $rules): array { + $conflictRules = [ + 'filled', 'nullable', 'required', 'required_if', 'required_unless', 'required_with', 'required_with_all', + 'required_without', 'required_without_all', 'present' + ]; foreach ($rules as $key => $rule) { - if (!in_array('filled', $rule) && !in_array('nullable', $rule)) { + if (empty(array_intersect($conflictRules, $rule))) { array_unshift($rule, 'filled'); $rules[$key] = $rule; } @@ -468,9 +472,9 @@ class Validate /** * 注册自定义验证方法 * - * @param string $rule 规则名称 + * @param string $rule 规则名称 * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator - * @param string|null $message 错误消息 + * @param string|null $message 错误消息 */ public static function extend(string $rule, $extension, ?string $message = null) { @@ -490,7 +494,7 @@ class Validate /** * 注册自定义验证方法错误消息 - * @param string $rule 规则名称 + * @param string $rule 规则名称 * @param string|Closure $replacer 闭包规则,回调四个值 $message,$attribute,$rule,$parameters */ public static function replacer(string $rule, $replacer) @@ -569,8 +573,8 @@ class Validate /** * 移除某个字段的验证规则 * - * @param string $field 字段名 - * @param string|null $rule 验证规则 null 移除所有规则 + * @param string $field 字段名 + * @param string|null $rule 验证规则 null 移除所有规则 * @return $this */ public function remove(string $field, ?string $rule = null): Validate @@ -616,9 +620,9 @@ class Validate /** * 复杂条件验证 * - * @param string|string[] $attribute 字段 - * @param string|array|BaseRule $rules 规则 - * @param callable $callback 回调方法,返回true获取具体规则生效 + * @param string|string[] $attribute 字段 + * @param string|array|BaseRule $rules 规则 + * @param callable $callback 回调方法,返回true获取具体规则生效 * @return $this */ public function sometimes($attribute, $rules, callable $callback): Validate @@ -682,8 +686,8 @@ class Validate /** * 获取验证消息 * - * @param null|string|string[] $key 完整消息Key值 - * @param string|null $rule 如果第一个值为字段名,则第二个值则为规则,否则请留空 + * @param null|string|string[] $key 完整消息Key值 + * @param string|null $rule 如果第一个值为字段名,则第二个值则为规则,否则请留空 * @return array|mixed|null */ public function getMessages($key = null, ?string $rule = null) -- Gitee From f5afcca470b8f7042c6ac60f4bd22949d465cc8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 10 Mar 2021 11:08:41 +0800 Subject: [PATCH 035/152] =?UTF-8?q?[U]=20=E4=BC=98=E5=8C=96=E8=A7=84?= =?UTF-8?q?=E5=88=99=E5=A4=84=E7=90=86=E7=9A=84=E4=BB=A3=E7=A0=81=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E4=BF=AE=E6=94=B9=E8=A7=84=E5=88=99=E7=9A=84=E5=85=88?= =?UTF-8?q?=E5=90=8E=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index adff207..d0b1dd1 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -124,12 +124,12 @@ class Validate try { $this->checkData = $data; $rule = $this->getSceneRules(); - if ($this->bail) { - $rule = $this->addBailRule($rule); - } if ($this->filled) { $rule = $this->addFilledRule($rule); } + if ($this->bail) { + $rule = $this->addBailRule($rule); + } $data = $this->handleEvent($data, 'beforeValidate'); /** @var \Illuminate\Validation\Validator $v */ $v = Validator::make($data, $rule, $this->message, $this->customAttributes); @@ -357,10 +357,9 @@ class Validate */ private function addBailRule(array $rules): array { - foreach ($rules as $key => $rule) { + foreach ($rules as $key => &$rule) { if (!in_array('bail', $rule)) { array_unshift($rule, 'bail'); - $rules[$key] = $rule; } } @@ -378,10 +377,9 @@ class Validate 'filled', 'nullable', 'required', 'required_if', 'required_unless', 'required_with', 'required_with_all', 'required_without', 'required_without_all', 'present' ]; - foreach ($rules as $key => $rule) { + foreach ($rules as $key => &$rule) { if (empty(array_intersect($conflictRules, $rule))) { array_unshift($rule, 'filled'); - $rules[$key] = $rule; } } @@ -683,6 +681,7 @@ class Validate $this->rule = array_merge($this->rule, $rules); return $this; } + /** * 获取验证消息 * @@ -726,7 +725,7 @@ class Validate } /** - * 设置验证场景(叠加) + * 设置验证场景数据(叠加) * * @param array|null $scene [场景 => [字段]] 如果$scene为null,则清空全部验证场景 * @return $this -- Gitee From 69f6dfef141a46af350070721cf84c75d0c4f728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 10 Mar 2021 16:13:56 +0800 Subject: [PATCH 036/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8Drequired?= =?UTF-8?q?=E7=AD=89=E8=A7=84=E5=88=99=E5=AD=98=E5=9C=A8=E6=97=B6=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0filled=E8=A7=84=E5=88=99=E7=9A=84=E4=B8=8D=E5=BF=85?= =?UTF-8?q?=E8=A6=81=E6=80=A7=20[A]=20=E5=A2=9E=E5=8A=A0extendImplicit?= =?UTF-8?q?=E6=96=B9=E6=B3=95=20[A]=20=E5=A2=9E=E5=8A=A0extendDependent?= =?UTF-8?q?=E6=96=B9=E6=B3=95=20[A]=20=E9=AA=8C=E8=AF=81=E5=99=A8=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=A2=9E=E5=8A=A0filled=E8=A7=84=E5=88=99=E6=97=B6?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9ImplicitRule=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=9A=84=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 4 +-- src/Validate.php | 94 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 89 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index e077707..51ff581 100644 --- a/composer.json +++ b/composer.json @@ -14,10 +14,10 @@ ], "require": { "php": "^7.4|^8.0", - "w7/rangine": "^2.4.7" + "w7/rangine": "^v2.4.10" }, "require-dev": { - "phpunit/phpunit" : "^8.5", + "phpunit/phpunit" : "^9.5", "friendsofphp/php-cs-fixer": "^2.18" }, "autoload": { diff --git a/src/Validate.php b/src/Validate.php index d0b1dd1..ea1402d 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -13,6 +13,7 @@ namespace W7\Validate; use Closure; +use Illuminate\Contracts\Validation\ImplicitRule; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Fluent; @@ -90,6 +91,12 @@ class Validate */ private static array $extendName = []; + /** + * 隐形扩展方法名 + * @var array + */ + private static array $implicitRules = []; + /** * 验证器事件处理类 * @var array @@ -374,11 +381,32 @@ class Validate public function addFilledRule(array $rules): array { $conflictRules = [ - 'filled', 'nullable', 'required', 'required_if', 'required_unless', 'required_with', 'required_with_all', - 'required_without', 'required_without_all', 'present' + 'filled', 'nullable', 'accepted', 'present', 'required', 'required_if', 'required_unless', 'required_with', + 'required_with_all', 'required_without', 'required_without_all', ]; + foreach ($rules as $key => &$rule) { - if (empty(array_intersect($conflictRules, $rule))) { + $rulesName = array_map(function ($value) { + $ruleClass = $this->getRuleClass($value, true); + // 如果继承了ImplicitRule标记接口 + // 代表此自定义规则想要在属性为空时执行规则对象 + // 所以也不需要添加filled规则,那么就让数组对象里存在一个filled + // 下面的判断就会自动跳过,实际上规则中没有被添加filled规则 + if (is_string($ruleClass) && is_subclass_of($ruleClass, ImplicitRule::class)) { + return 'filled'; + } + + $ruleName = $this->getKeyAndParam($value)[0]; + + // 此处操作同上 + if (in_array($ruleName, self::$implicitRules)) { + return 'filled'; + } + + return $ruleName; + }, $rule); + + if (empty(array_intersect($conflictRules, $rulesName))) { array_unshift($rule, 'filled'); } } @@ -450,17 +478,22 @@ class Validate /** * 获取自定义规则的实例类 * - * @param string $ruleName 自定义规则名称 + * @param string $ruleName 自定义规则名称 + * @param bool $ruleClassName 是否只获取Class完整命名空间 默认为false * @return false|mixed|Closure */ - private function getRuleClass(string $ruleName) + private function getRuleClass(string $ruleName, bool $ruleClassName = false) { list($ruleName, $param) = $this->getKeyAndParam($ruleName, true); foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { $ruleNameSpace = $rulesPath . ucfirst($ruleName); if (class_exists($ruleNameSpace)) { - return new $ruleNameSpace(...$param); + if ($ruleClassName) { + return $ruleNameSpace; + } else { + return new $ruleNameSpace(...$param); + } } } @@ -475,6 +508,42 @@ class Validate * @param string|null $message 错误消息 */ public static function extend(string $rule, $extension, ?string $message = null) + { + self::validatorExtend('', $rule, $extension, $message); + } + + /** + * 注册一个自定义的隐式验证器扩展 + * + * @param string $rule 规则名称 + * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator + * @param string|null $message 错误消息 + */ + public static function extendImplicit(string $rule, $extension, ?string $message = null) + { + self::validatorExtend('Implicit', $rule, $extension, $message); + } + + /** + * 注册一个自定义依赖性验证器扩展 + * + * @param string $rule 规则名称 + * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator + * @param string|null $message 错误消息 + */ + public static function extendDependent(string $rule, $extension, ?string $message = null) + { + self::validatorExtend('Dependent', $rule, $extension, $message); + } + + /** + * 注册自定义验证器扩展 + * @param string $type 类型 + * @param string $rule 规则名称 + * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator + * @param string|null $message 错误消息 + */ + private static function validatorExtend(string $type, string $rule, $extension, ?string $message = null) { $ruleName = md5(get_called_class() . $rule); @@ -487,7 +556,18 @@ class Validate # 多个验证器使用了同样的rule会导致后面的方法无法生效 # 故这里根据命名空间生成一个独一无二的rule名称 $ruleName = md5(get_called_class() . $rule); - Validator::extend($ruleName, $extension, $message); + + if (!empty($type)) { + $method = 'extend' . $type; + } else { + $method = 'extend'; + } + + if ('Implicit' === $type) { + self::$implicitRules[] = $ruleName; + } + + Validator::$method($ruleName, $extension, $message); } /** -- Gitee From f5b97305dbd2c5adf7cf65e2950ba77346a454af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 10 Mar 2021 16:18:14 +0800 Subject: [PATCH 037/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9addFilledRule?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E7=9A=84=E5=8F=AF=E8=A7=81=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Validate.php b/src/Validate.php index ea1402d..0632544 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -378,7 +378,7 @@ class Validate * @param array $rules 原规则 * @return array */ - public function addFilledRule(array $rules): array + private function addFilledRule(array $rules): array { $conflictRules = [ 'filled', 'nullable', 'accepted', 'present', 'required', 'required_if', 'required_unless', 'required_with', -- Gitee From 2044ee09b624dea589f76837d70ee702a3a9a2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 10 Mar 2021 16:44:59 +0800 Subject: [PATCH 038/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0getData?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 0632544..2dbf9a7 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -68,7 +68,7 @@ class Validate protected bool $bail = true; /** - * 所有验证的字段在存在时不能为空,规则中带nullable除外 + * 所有验证的字段在存在时不能为空 * @var bool */ protected bool $filled = true; @@ -107,13 +107,13 @@ class Validate * Request请求实例 * @var RequestInterface|null */ - protected ?RequestInterface $request = null; + private ?RequestInterface $request = null; /** * 当前进行验证的数据 * @var array */ - protected array $checkData = []; + private array $checkData = []; public function __construct(?RequestInterface $request = null) { @@ -154,6 +154,15 @@ class Validate } } + /** + * 获取当前的验证数据 + * @return array + */ + public function getData(): array + { + return $this->checkData; + } + /** * 处理错误消息 * @param array $errors -- Gitee From 341acf9c3f28256840f98a7584cf85ffd8290254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 11 Mar 2021 10:59:27 +0800 Subject: [PATCH 039/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E5=BD=93?= =?UTF-8?q?=E8=A7=84=E5=88=99=E6=98=AF=E4=B8=80=E4=B8=AA=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E8=A7=84=E5=88=99=E6=97=B6=E5=BC=95=E5=8F=91=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 2dbf9a7..f1ec51a 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -396,13 +396,17 @@ class Validate foreach ($rules as $key => &$rule) { $rulesName = array_map(function ($value) { - $ruleClass = $this->getRuleClass($value, true); - // 如果继承了ImplicitRule标记接口 - // 代表此自定义规则想要在属性为空时执行规则对象 - // 所以也不需要添加filled规则,那么就让数组对象里存在一个filled - // 下面的判断就会自动跳过,实际上规则中没有被添加filled规则 - if (is_string($ruleClass) && is_subclass_of($ruleClass, ImplicitRule::class)) { - return 'filled'; + if (is_object($value)) { + $className = get_class($value); + // 如果继承了ImplicitRule标记接口 + // 代表此自定义规则想要在属性为空时执行规则对象 + // 所以也不需要添加filled规则,那么就让数组对象里存在一个filled + // 下面的判断就会自动跳过,实际上规则中没有被添加filled规则 + if (is_subclass_of($className, ImplicitRule::class)) { + return 'filled'; + } else { + return $className; + } } $ruleName = $this->getKeyAndParam($value)[0]; -- Gitee From 9ea6c27ee434b8f34118ce8a7e784aeeea5e9a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 11 Mar 2021 11:09:29 +0800 Subject: [PATCH 040/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E6=A0=87=E8=AE=B0=E6=8E=A5=E5=8F=A3=E7=9A=84=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index f1ec51a..c9c0074 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -397,15 +397,14 @@ class Validate foreach ($rules as $key => &$rule) { $rulesName = array_map(function ($value) { if (is_object($value)) { - $className = get_class($value); // 如果继承了ImplicitRule标记接口 // 代表此自定义规则想要在属性为空时执行规则对象 // 所以也不需要添加filled规则,那么就让数组对象里存在一个filled // 下面的判断就会自动跳过,实际上规则中没有被添加filled规则 - if (is_subclass_of($className, ImplicitRule::class)) { + if ($value instanceof ImplicitRule) { return 'filled'; } else { - return $className; + return ''; } } -- Gitee From 433cd680e05046f7c45000baf18b7046aa10db13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 2 Apr 2021 14:41:48 +0800 Subject: [PATCH 041/152] =?UTF-8?q?[A]=20=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E8=A7=84=E5=88=99=E6=94=AF=E6=8C=81=E7=B1=BB=E6=96=B9=E6=B3=95?= =?UTF-8?q?=20[A]=20=E8=87=AA=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E7=B1=BB?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9F=BA=E7=B1=BB=E7=9A=84=E5=88=A4=E6=96=AD?= =?UTF-8?q?=E6=9D=A5=E9=81=BF=E5=85=8D=E4=BD=BF=E7=94=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index c9c0074..fd7f1fb 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -266,6 +266,11 @@ class Validate } return $ruleClass; } + + if (method_exists($this, 'rule' . ucfirst($value))) { + self::extend($value, Closure::fromCallable([$this, 'rule' . ucfirst($value)])); + } + return $this->getExtendsName($value, $field); } return $value; @@ -287,7 +292,6 @@ class Validate list($rule, $param) = $this->getKeyAndParam($rule, false); # 取回真实的自定义规则方法名称,以及修改对应的错误消息 - if (array_key_exists($rule, self::$extendName)) { $ruleName = md5(get_called_class() . $rule); # 判断是否为自定义规则方法定义了错误消息 @@ -500,7 +504,7 @@ class Validate foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { $ruleNameSpace = $rulesPath . ucfirst($ruleName); - if (class_exists($ruleNameSpace)) { + if (class_exists($ruleNameSpace) && is_subclass_of($ruleNameSpace, BaseRule::class)) { if ($ruleClassName) { return $ruleNameSpace; } else { -- Gitee From caf77c5fc114cc57eb6705399c9e5a1e4954636f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 2 Apr 2021 16:35:04 +0800 Subject: [PATCH 042/152] =?UTF-8?q?[D]=20=E5=88=A0=E9=99=A4=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E8=87=AA=E5=AE=9A=E4=B9=89=E9=AA=8C=E8=AF=81=E8=A7=84?= =?UTF-8?q?=E5=88=99=E5=90=8D=E7=A7=B0=E7=9A=84=E9=87=8D=E5=A4=8D=E5=80=BC?= =?UTF-8?q?=EF=BC=8C=E8=8A=82=E7=BA=A6=E5=86=85=E5=AD=98=E5=8D=A0=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++++------ src/Validate.php | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d5ac111..7482d17 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,14 @@ ## 说明 此验证基于Laravel的Validator验证器,做了如下改变 - - 可通过类的方式定义一个[验证器](https://wiki.w7.cc/chapter/868?id=3234) - - 增加[验证场景](https://wiki.w7.cc/chapter/868?id=3233) - - 增加[场景事件处理](https://wiki.w7.cc/chapter/868?id=3232) - - 修改了[自定义验证规则](https://wiki.w7.cc/chapter/868?id=3231) + - 可通过类的方式定义一个[验证器](https://v.neww7.com/Validate.htm) + - 增加[验证场景](https://v.neww7.com/Scene.html) + - 增加[场景事件处理](https://v.neww7.com/Event.html) + - 修改了[自定义验证规则](https://v.neww7.com/Rule.html) -此文档只说明与Laravel的Validator验证器不同的地方,完整Laravel Validator文档可查看:[完整文档](https://learnku.com/docs/laravel/6.x/validation/5144) +等... + +> 此文档只说明与Laravel的Validator验证器不同的地方,完整Laravel Validator文档可查看:[完整文档](https://learnku.com/docs/laravel/6.x/validation/5144) ## 安装 使用composer命令 @@ -15,4 +17,4 @@ composer require w7/rangine-validate ``` -完整文档查看[完整文档](https://wiki.w7.cc/chapter/868?id=3235) \ No newline at end of file +完整文档查看[完整文档](https://v.neww7.com) \ No newline at end of file diff --git a/src/Validate.php b/src/Validate.php index fd7f1fb..a70c29b 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -565,6 +565,7 @@ class Validate if (array_key_exists($rule, self::$extendName)) { array_push(self::$extendName[$rule], $ruleName); + self::$extendName[$rule] = array_unique(self::$extendName[$rule]); } else { self::$extendName[$rule] = [$ruleName]; } -- Gitee From abfb10de4d5e508b25761b454d3c988c3492bbca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 6 Apr 2021 18:46:14 +0800 Subject: [PATCH 043/152] =?UTF-8?q?[A]=20=E9=AA=8C=E8=AF=81=E9=9B=86?= =?UTF-8?q?=E5=90=88=E7=9A=84Get=E6=96=B9=E6=B3=95=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AF=B9`*`=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 944c9b1..dd899d0 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -184,6 +184,28 @@ class ValidateCollection extends Collection { if (false !== strpos($key, '.')) { $value = Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); + } elseif (false !== strpos($key, '*')) { + $_value = explode('.', $key); + $_data = $this->items; + + while (false !== ($index = array_search('*', $_value))) { + $_key = array_slice($_value, 0, $index); + $_pluckKey = array_slice($_value, $index + 1, 1); + $_value = array_slice($_value, $index + 2); + + if (empty($_key)) { + $_data = Arr::pluck($_data, $_pluckKey); + } else { + $_data = Arr::pluck(Arr::get($_data, implode('.', $_key)), $_pluckKey); + } + } + + if (!empty($_value)) { + $_value = implode(',', $_value); + $_data = Arr::get($_data, $_value); + } + + $value = $_data ?: ($default instanceof Closure ? $default() : $default); } else { $value = parent::get($key, $default); } -- Gitee From c0daac71b9846ecb13fa197148d6e36900387e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 13 Apr 2021 22:57:29 +0800 Subject: [PATCH 044/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=89=8D=E6=89=A7=E8=A1=8C=E6=96=B9=E6=B3=95=20[A]=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=AA=8C=E8=AF=81=E5=90=8E=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 4 +- src/Validate.php | 216 +++++++++++++++--- ...rticleValidate.php => ArticleValidate.php} | 2 +- tests/Material/HandlerDataValidate.php | 39 ++++ tests/TestHandlerFunction.php | 41 ++++ tests/TestValidateScene.php | 12 +- 6 files changed, 276 insertions(+), 38 deletions(-) rename tests/Material/{TestArticleValidate.php => ArticleValidate.php} (97%) create mode 100644 tests/Material/HandlerDataValidate.php create mode 100644 tests/TestHandlerFunction.php diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index dd899d0..9a95a0e 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -175,8 +175,8 @@ class ValidateCollection extends Collection /** * 获取指定字段的值 - * @param mixed $key 字段名称 - * @param null $default 默认值 + * @param mixed $key 字段名称 + * @param mixed|Closure|null $default 默认值 * @return array|ArrayAccess|mixed * @throws CollectionException */ diff --git a/src/Validate.php b/src/Validate.php index a70c29b..1ad8752 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -103,6 +103,18 @@ class Validate */ private array $handlers = []; + /** + * 验证前需要执行的方法 + * @var array + */ + private array $befores = []; + + /** + * 验证后需要执行的方法 + * @var array + */ + private array $afters = []; + /** * Request请求实例 * @var RequestInterface|null @@ -138,14 +150,15 @@ class Validate $rule = $this->addBailRule($rule); } $data = $this->handleEvent($data, 'beforeValidate'); + $data = $this->handleCallback($data, 1); /** @var \Illuminate\Validation\Validator $v */ $v = Validator::make($data, $rule, $this->message, $this->customAttributes); - $data = $this->handleEvent($v->validate(), 'afterValidate'); - return $data; + $data = $this->handleCallback($v->validate(), 2); + return $this->handleEvent($data, 'afterValidate'); } catch (ValidationException $e) { $errors = $this->handlingError($e->errors()); $errorMessage = ''; - foreach ($errors as $field => $message) { + foreach ($errors as $message) { $errorMessage = $message[0]; break; } @@ -170,7 +183,7 @@ class Validate */ private function handlingError(array $errors): array { - foreach ($errors as $field => &$errorMessages) { + foreach ($errors as &$errorMessages) { if (is_array($errorMessages)) { $errorMessages = array_map([$this, 'replacingFieldsInMessage'], $errorMessages); } else { @@ -187,7 +200,7 @@ class Validate */ private function replacingFieldsInMessage(string $message) { - if (preg_match_all('/\{:(.*?)}/', $message, $matches) > 0) { + if (preg_match_all('/{:(.*?)}/', $message, $matches) > 0) { foreach ($matches[0] as $index => $pregString) { $message = str_replace($pregString, Arr::get($this->checkData, $matches[1][$index], ''), $message); } @@ -195,6 +208,65 @@ class Validate return $message; } + /** + * 处理方法 + * @param array $data + * @param int $type 类型,1 验证前方法 2 验证后方法 + * @return array + * @throws ValidateException + */ + private function handleCallback(array $data, int $type): array + { + switch ($type) { + case 1: + $callbacks = $this->befores; + $typeName = 'before'; + break; + case 2: + $callbacks = $this->afters; + $typeName = 'after'; + break; + default: + throw new LogicException('Type Error'); + } + + if (empty($callbacks)) { + return $data; + } + + $callback = array_map(function ($callback) use ($typeName) { + return function ($data, $next) use ($callback, $typeName) { + list($callback, $param) = $callback; + $callback = $typeName . ucfirst($callback); + if (method_exists($this, $callback)) { + return call_user_func([$this, $callback], $data, $next, ...$param); + } + throw new LogicException('Method Not Found'); + }; + }, $callbacks); + + $pipeline = array_reduce( + array_reverse($callback), + function ($stack, $pipe) { + return function ($data) use ($stack, $pipe) { + return $pipe($data, $stack); + }; + }, + function ($data) { + return $data; + } + ); + $data = $pipeline($data); + + if (is_string($data)) { + throw new ValidateException($data, 403); + } elseif (is_array($data)) { + return $data; + } + + throw new LogicException('Validate event return type error'); + } + /** * 验证事件处理 * @param array $data 验证的数据 @@ -236,6 +308,8 @@ class Validate { $this->checkRule = collect([]); $this->handlers = []; + $this->afters = []; + $this->befores = []; } /** @@ -353,17 +427,60 @@ class Validate */ private function addHandler($handlers) { - if (is_string($handlers)) { - $this->handlers[] = [$handlers, []]; + $this->addCallback(0, $handlers); + } + + /** + * 添加验证前方法 + * @param $callback + */ + private function addBefore($callback) + { + $this->addCallback(1, $callback); + } + + /** + * 添加验证后方法 + * @param $callback + */ + private function addAfter($callback) + { + $this->addCallback(2, $callback); + } + + /** + * 添加方法 + * @param int $intType 0为事件 1为验证前方法 2为验证后方法 + * @param $callback + */ + private function addCallback(int $intType, $callback) + { + switch ($intType) { + case 0: + $type = 'handlers'; + break; + case 1: + $type = 'befores'; + break; + case 2: + $type = 'afters'; + break; + default: + throw new LogicException('Type Error'); + } + + if (is_string($callback)) { + $this->$type[] = [$callback, []]; } else { - foreach ($handlers as $handlerClass => $param) { - if (is_int($handlerClass)) { - $this->handlers[] = [$param, []]; - } elseif (is_string($handlerClass)) { + foreach ($callback as $classOrMethod => $param) { + if (is_int($classOrMethod)) { + $this->$type[] = [$param, []]; + } elseif (is_string($classOrMethod)) { + $callbackName = str_replace('s', '', $type); if (is_array($param)) { - $this->handler($handlerClass, ...$param); + $this->$callbackName($classOrMethod, ...$param); } else { - $this->handler($handlerClass, $param); + $this->$callbackName($classOrMethod, $param); } } } @@ -377,7 +494,7 @@ class Validate */ private function addBailRule(array $rules): array { - foreach ($rules as $key => &$rule) { + foreach ($rules as &$rule) { if (!in_array('bail', $rule)) { array_unshift($rule, 'bail'); } @@ -398,7 +515,7 @@ class Validate 'required_with_all', 'required_without', 'required_without_all', ]; - foreach ($rules as $key => &$rule) { + foreach ($rules as &$rule) { $rulesName = array_map(function ($value) { if (is_object($value)) { // 如果继承了ImplicitRule标记接口 @@ -433,14 +550,14 @@ class Validate /** * 进入场景 * @param string|null $name 场景名称 - * @return Validate + * @return void * @throws ValidateException */ - private function getScene(?string $name = null): Validate + private function getScene(?string $name = null): void { if (empty($name)) { $this->checkRule = collect($this->rule); - return $this; + return; } # 判断自定义验证场景是否存在 if (method_exists($this, 'scene' . ucfirst($name))) { @@ -457,6 +574,22 @@ class Validate unset($this->scene[$name]['handler']); } + # 判断是否定义了验证前需要执行的方法 + if (isset($sceneRule['before'])) { + $callback = $sceneRule['before']; + $this->addBefore($callback); + unset($sceneRule['before']); + unset($this->scene[$name]['before']); + } + + # 判断是否定义了验证后需要执行的方法 + if (isset($sceneRule['after'])) { + $callback = $sceneRule['after']; + $this->addAfter($callback); + unset($sceneRule['after']); + unset($this->scene[$name]['after']); + } + # 判断验证场景是否指定了其他验证场景 if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { $use = $sceneRule['use']; @@ -476,7 +609,7 @@ class Validate $use = call_user_func([$this, 'use' . ucfirst($use)], $data); if (is_array($use)) { $this->checkRule = collect($this->rule)->only($use); - return $this; + return; } } $this->getScene($use); @@ -487,8 +620,6 @@ class Validate # 如果验证场景找不到,则默认验证全部规则 $this->checkRule = collect($this->rule); } - - return $this; } /** @@ -617,7 +748,6 @@ class Validate /** * 加入事件 - * * @param string $handler 事件的完整类名,完整命名空间字符串或者加::class * @param mixed ...$params 要传递给事件的参数 * @return $this @@ -628,6 +758,30 @@ class Validate return $this; } + /** + * 加入验证器验证前的方法 + * @param string $callbackName 本类的方法名 + * @param mixed ...$params 要传递给方法的参数 + * @return $this + */ + public function before(string $callbackName, ...$params): Validate + { + $this->befores[] = [$callbackName, $params]; + return $this; + } + + /** + * 加入验证器验证后的方法 + * @param string $callbackName 本类的方法名 + * @param mixed ...$params 要传递给方法的参数 + * @return $this + */ + public function after(string $callbackName, ...$params): Validate + { + $this->afters[] = [$callbackName, $params]; + return $this; + } + /** * 指定需要验证的字段列表 * @@ -772,10 +926,12 @@ class Validate */ public function setRules(?array $rules = null): Validate { - if (null === $rules) { + if (is_null($rules)) { $this->rule = []; + } else { + $this->rule = array_merge($this->rule, $rules); } - $this->rule = array_merge($this->rule, $rules); + return $this; } @@ -813,11 +969,12 @@ class Validate */ public function setMessages(?array $message = null): Validate { - if (null === $message) { + if (is_null($message)) { $this->message = []; + } else { + $this->message = array_merge($this->message, $message); } - - $this->message = array_merge($this->message, $message); + return $this; } @@ -829,11 +986,12 @@ class Validate */ public function setScene(?array $scene = null): Validate { - if (null === $scene) { + if (is_null($scene)) { $this->scene = []; + } else { + $this->scene = array_merge($this->scene, $scene); } - $this->scene = array_merge($this->scene, $scene); return $this; } } diff --git a/tests/Material/TestArticleValidate.php b/tests/Material/ArticleValidate.php similarity index 97% rename from tests/Material/TestArticleValidate.php rename to tests/Material/ArticleValidate.php index 1e6cbd7..d83136c 100644 --- a/tests/Material/TestArticleValidate.php +++ b/tests/Material/ArticleValidate.php @@ -14,7 +14,7 @@ namespace W7\Tests\Material; use W7\Validate\Validate; -class TestArticleValidate extends Validate +class ArticleValidate extends Validate { protected array $rule = [ 'id' => 'required|numeric', diff --git a/tests/Material/HandlerDataValidate.php b/tests/Material/HandlerDataValidate.php new file mode 100644 index 0000000..4cb13c1 --- /dev/null +++ b/tests/Material/HandlerDataValidate.php @@ -0,0 +1,39 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material; + +use W7\Validate\Validate; + +class HandlerDataValidate extends Validate +{ + protected array $rule = [ + 'user' => 'required|array', + 'user.*' => 'chsAlphaNum' + ]; + + protected array $scene = [ + 'test' => ['user', 'user.*', 'after' => 'checkUserNotRepeat'] + ]; + + public function afterCheckUserNotRepeat(array $data, $next) + { + $uniqueData = array_unique($data['user']); + + if (count($data['user']) === count($uniqueData)) { + $data['user'][] = 'c'; + return $next($data); + } + + return '用户信息重复'; + } +} diff --git a/tests/TestHandlerFunction.php b/tests/TestHandlerFunction.php new file mode 100644 index 0000000..b8bd509 --- /dev/null +++ b/tests/TestHandlerFunction.php @@ -0,0 +1,41 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests; + +use W7\Tests\Material\HandlerDataValidate; +use W7\Tests\Material\TestBaseValidate; + +class TestHandlerFunction extends TestBaseValidate +{ + public function testAfterRule() + { + $v = new HandlerDataValidate(); + + $this->expectExceptionMessage('用户信息重复'); + + $v->scene('test')->check(['user' => [ + 'a', 'a' + ]]); + } + + public function testAfterDataHandler() + { + $v = new HandlerDataValidate(); + + $data = $v->scene('test')->check(['user' => [ + 'a', 'b' + ]]); + + $this->assertCount(3, $data['user']); + } +} diff --git a/tests/TestValidateScene.php b/tests/TestValidateScene.php index 8498520..fd3aa19 100644 --- a/tests/TestValidateScene.php +++ b/tests/TestValidateScene.php @@ -12,7 +12,7 @@ namespace W7\Tests; -use W7\Tests\Material\TestArticleValidate; +use W7\Tests\Material\ArticleValidate; use W7\Tests\Material\TestBaseValidate; use W7\Validate\Exception\ValidateException; @@ -35,7 +35,7 @@ class TestValidateScene extends TestBaseValidate */ public function testNotScene() { - $v = new TestArticleValidate(); + $v = new ArticleValidate(); $this->expectException(ValidateException::class); $v->check($this->userInput); } @@ -46,7 +46,7 @@ class TestValidateScene extends TestBaseValidate */ public function testScene() { - $v = new TestArticleValidate(); + $v = new ArticleValidate(); $data = $v->scene('add')->check($this->userInput); $this->assertEquals('内容', $data['content']); } @@ -57,7 +57,7 @@ class TestValidateScene extends TestBaseValidate */ public function testCustomScene() { - $validate = new TestArticleValidate(); + $validate = new ArticleValidate(); $this->expectException(ValidateException::class); $validate->scene('edit')->check($this->userInput); } @@ -68,14 +68,14 @@ class TestValidateScene extends TestBaseValidate */ public function testUseScene() { - $validate = new TestArticleValidate(); + $validate = new ArticleValidate(); $this->expectExceptionMessage('缺少参数:文章Id'); $validate->scene('save')->check($this->userInput); } public function testDynamicScene() { - $validate = new TestArticleValidate(); + $validate = new ArticleValidate(); $data = $validate->scene('dynamic')->check([ 'title' => '标题标题标题标题', 'content' => '1' -- Gitee From 18b5db658db4d1f7de76f87829eec765ae0ed9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 14 Apr 2021 14:58:19 +0800 Subject: [PATCH 045/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=99=A8=E9=9B=86=E5=90=88Get=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=B8=A6*=E5=8F=B7=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=95=B0=E6=8D=AE=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20[A]=20=E5=A2=9E=E5=8A=A0=E9=AA=8C=E8=AF=81=E5=99=A8=E9=9B=86?= =?UTF-8?q?=E5=90=88=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 6 +- src/Validate.php | 5 +- tests/TestValidateCollection.php | 177 +++++++++++++++++++++ 3 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 tests/TestValidateCollection.php diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 9a95a0e..9f38945 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -182,9 +182,7 @@ class ValidateCollection extends Collection */ public function get($key, $default = null) { - if (false !== strpos($key, '.')) { - $value = Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); - } elseif (false !== strpos($key, '*')) { + if (false !== strpos($key, '*')) { $_value = explode('.', $key); $_data = $this->items; @@ -206,6 +204,8 @@ class ValidateCollection extends Collection } $value = $_data ?: ($default instanceof Closure ? $default() : $default); + } elseif (false !== strpos($key, '.')) { + $value = Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); } else { $value = parent::get($key, $default); } diff --git a/src/Validate.php b/src/Validate.php index 1ad8752..91c1394 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -252,10 +252,9 @@ class Validate return $pipe($data, $stack); }; }, - function ($data) { - return $data; - } + fn ($data) => $data ); + $data = $pipeline($data); if (is_string($data)) { diff --git a/tests/TestValidateCollection.php b/tests/TestValidateCollection.php new file mode 100644 index 0000000..7e797ce --- /dev/null +++ b/tests/TestValidateCollection.php @@ -0,0 +1,177 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests; + +use W7\Tests\Material\TestBaseValidate; + +class TestValidateCollection extends TestBaseValidate +{ + public function testGetMultiDimensionalArrays() + { + $data = [ + 'a' => [ + 'b' => [ + 'c' => 123 + ] + ] + ]; + + $this->assertEquals(123, validate_collect($data)->get('a.b.c')); + } + + public function testGetArrayPluck() + { + $data = [ + 'I7 1700K' => [ + 'vendor' => 'Inter' + ], + 'R7 5800X' => [ + 'vendor' => 'AMD' + ], + 'I9 11900K' => [ + 'vendor' => 'Inter' + ], + 'A10-9700' => [ + 'vendor' => 'AMD' + ] + ]; + + $this->assertEquals([ + 'Inter', + 'AMD', + 'Inter', + 'AMD' + ], validate_collect($data)->get('*.vendor')); + } + + public function testTypeConversion() + { + $data = [ + 'age' => '20' + ]; + + $this->assertEquals(20, validate_collect($data)->int()->get('age')); + $this->assertEquals([20], validate_collect($data)->array()->get('age')); + $this->assertEquals(true, validate_collect($data)->bool()->get('age')); + $this->assertEquals('20', validate_collect($data)->string()->get('age')); + + $data = [ + 'age' => '20.05' + ]; + + $this->assertEquals(20, validate_collect($data)->int()->get('age')); + $this->assertEquals(20.05, validate_collect($data)->float()->get('age')); + $data = [ + 'age' => 20 + ]; + + $this->assertEquals('20', validate_collect($data)->string()->get('age')); + } + + public function testShift() + { + $data = validate_collect([1, 2, 3, 4]); + + $this->assertEquals(1, $data->shift()); + $this->assertEquals(2, $data->shift()); + $this->assertEquals(3, $data->shift()); + $this->assertEquals(4, $data->shift()); + $this->assertEquals(null, $data->shift()); + } + + public function testPop() + { + $data = validate_collect([1, 2, 3, 4]); + + $this->assertEquals(4, $data->pop()); + $this->assertEquals(3, $data->pop()); + $this->assertEquals(2, $data->pop()); + $this->assertEquals(1, $data->pop()); + $this->assertEquals(null, $data->pop()); + } + + public function testPull() + { + $data = validate_collect([ + 'name' => 'yuyu', + 'age' => 2 + ]); + + $this->assertEquals('yuyu', $data->pull('name')); + $this->assertFalse($data->has('name')); + $this->assertEquals([ + 'age' => 2 + ], $data->all()); + } + + public function testHas() + { + $data = validate_collect([ + 'user' => [ + 'name' => 'yuyu', + 'age' => 1 + ] + ]); + + $this->assertTrue($data->has('user')); + $this->assertTrue($data->has('user.name')); + $this->assertTrue($data->has('user.age')); + $this->assertFalse($data->has('user.phone')); + } + + public function testSet() + { + $data = validate_collect([ + 'user' => [ + 'name' => 'yuyu', + 'age' => 1 + ] + ]); + + $this->assertFalse($data->has('user.phone')); + + $data->set('user.phone', '13122223333'); + $this->assertTrue($data->has('user.phone')); + $this->assertEquals('13122223333', $data->get('user.phone')); + + $data->set('count', 1); + $this->assertTrue($data->has('count')); + $this->assertEquals(1, $data->get('count')); + } + + public function testWhenHas() + { + $data = validate_collect([ + 'name' => 'yuyu' + ]); + $this->assertNull($data->get('have')); + $data->whenHas('name', function ($data) { + $data->set('have', true); + }); + + $this->assertTrue($data->get('have')); + } + + public function testWhenNotHas() + { + $data = validate_collect(); + + $this->assertNull($data->get('have')); + + $data->whenNotHas('name', function ($data) { + $data->set('have', false); + }); + + $this->assertFalse($data->get('have')); + } +} -- Gitee From 94f04c637e2b9a781fd8470ee1e1e51f8beec2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 14 Apr 2021 15:37:29 +0800 Subject: [PATCH 046/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=99=A8=E4=BA=8B=E4=BB=B6=E6=96=B9=E6=B3=95=E7=9A=84?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 -- composer.json | 3 ++ phpunit.xml | 7 ++++ tests/Material/HandlerDataValidate.php | 33 +++++++++++++-- tests/Material/Rules/Chs.php | 36 ++++++++++++++++ tests/{ => Test}/TestHandlerFunction.php | 46 +++++++++++++++++++-- tests/{ => Test}/TestValidateCollection.php | 2 +- tests/{ => Test}/TestValidateScene.php | 8 +++- 8 files changed, 125 insertions(+), 14 deletions(-) create mode 100644 phpunit.xml create mode 100644 tests/Material/Rules/Chs.php rename tests/{ => Test}/TestHandlerFunction.php (33%) rename tests/{ => Test}/TestValidateCollection.php (99%) rename tests/{ => Test}/TestValidateScene.php (95%) diff --git a/.gitignore b/.gitignore index a6696cb..e6979f2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,12 +7,8 @@ temp/ runtime/ *.lock .DS_Store -Dockerfile -docker-compose.yml -phpunit.xml .phpstorm.meta* /.env /vendor -/.php_cs /.idea /composer.lock diff --git a/composer.json b/composer.json index 51ff581..726f7c2 100644 --- a/composer.json +++ b/composer.json @@ -8,6 +8,9 @@ "email": "995645888@qq.com" } ], + "scripts": { + "test" : "phpunit --configuration phpunit.xml" + }, "keywords": [ "w7", "validate" diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..9957e07 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,7 @@ + + + + tests\Test + + + \ No newline at end of file diff --git a/tests/Material/HandlerDataValidate.php b/tests/Material/HandlerDataValidate.php index 4cb13c1..8d53b28 100644 --- a/tests/Material/HandlerDataValidate.php +++ b/tests/Material/HandlerDataValidate.php @@ -18,22 +18,49 @@ class HandlerDataValidate extends Validate { protected array $rule = [ 'user' => 'required|array', - 'user.*' => 'chsAlphaNum' + 'user.*' => 'chsAlphaNum', + 'name' => 'required|Chs' ]; protected array $scene = [ - 'test' => ['user', 'user.*', 'after' => 'checkUserNotRepeat'] + 'afterRule' => ['user', 'user.*', 'after' => 'checkUserNotRepeat'], + 'addData' => ['user', 'user.*', 'after' => 'addData'], + 'beforeHandlerData' => ['name', 'before' => 'setDefaultName'], + 'beforeSetDefaultNameIsError' => ['name', 'before' => 'setDefaultNameIsError'] ]; + public function afterAddData(array $data, $next) + { + $data['user'][] = 'c'; + return $next($data); + } + public function afterCheckUserNotRepeat(array $data, $next) { $uniqueData = array_unique($data['user']); if (count($data['user']) === count($uniqueData)) { - $data['user'][] = 'c'; return $next($data); } return '用户信息重复'; } + + public function beforeSetDefaultName(array $data, $next) + { + if (isset($data['name']) || empty($data['name'])) { + $data['name'] = '张三'; + } + + return $next($data); + } + + public function beforeSetDefaultNameIsError(array $data, $next) + { + if (isset($data['name']) || empty($data['name'])) { + $data['name'] = 'test'; + } + + return $next($data); + } } diff --git a/tests/Material/Rules/Chs.php b/tests/Material/Rules/Chs.php new file mode 100644 index 0000000..e0425b9 --- /dev/null +++ b/tests/Material/Rules/Chs.php @@ -0,0 +1,36 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material\Rules; + +use W7\Validate\Support\Rule\BaseRule; + +class Chs extends BaseRule +{ + /** + * 默认错误消息 + * @var string + */ + protected string $message = ':attribute的值只能具有中文'; + + /** + * 确定验证规则是否通过。 + * + * @param mixed $attribute + * @param mixed $value + * @return bool + */ + public function passes($attribute, $value): bool + { + return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$value); + } +} diff --git a/tests/TestHandlerFunction.php b/tests/Test/TestHandlerFunction.php similarity index 33% rename from tests/TestHandlerFunction.php rename to tests/Test/TestHandlerFunction.php index b8bd509..3e46d05 100644 --- a/tests/TestHandlerFunction.php +++ b/tests/Test/TestHandlerFunction.php @@ -10,32 +10,70 @@ * visited https://www.w7.cc for more details */ -namespace W7\Tests; +namespace W7\Tests\Test; use W7\Tests\Material\HandlerDataValidate; use W7\Tests\Material\TestBaseValidate; class TestHandlerFunction extends TestBaseValidate { + /** + * @test 测试在after中进行最后的验证 + * @throws \W7\Validate\Exception\ValidateException + */ public function testAfterRule() { $v = new HandlerDataValidate(); $this->expectExceptionMessage('用户信息重复'); - $v->scene('test')->check(['user' => [ + $v->scene('afterRule')->check(['user' => [ 'a', 'a' ]]); } - public function testAfterDataHandler() + /** + * @test 测试在after方法中对数据进行处理 + * @throws \W7\Validate\Exception\ValidateException + */ + public function testAfterAddData() { $v = new HandlerDataValidate(); - $data = $v->scene('test')->check(['user' => [ + $data = $v->scene('addData')->check(['user' => [ 'a', 'b' ]]); $this->assertCount(3, $data['user']); } + + /** + * @test 测试在before方法中对值设定一个默认值 + * @throws \W7\Validate\Exception\ValidateException + */ + public function testBeforeHandlerData() + { + $v = new HandlerDataValidate(); + + $data = $v->scene('beforeHandlerData')->check([]); + + $this->assertEquals('张三', $data['name']); + + $data = $v->scene('beforeHandlerData')->check(['name' => '李四']); + + $this->assertEquals('李四', $data['name']); + } + + /** + * @test 测试在before方法中对值设定一个不符合规则的默认值 + * @throws \W7\Validate\Exception\ValidateException + */ + public function testBeforeHandlerToVerifySetDefaultValues() + { + $v = new HandlerDataValidate(); + + $this->expectExceptionMessage('名称的值只能具有中文'); + + $v->scene('beforeSetDefaultNameIsError')->check([]); + } } diff --git a/tests/TestValidateCollection.php b/tests/Test/TestValidateCollection.php similarity index 99% rename from tests/TestValidateCollection.php rename to tests/Test/TestValidateCollection.php index 7e797ce..e581056 100644 --- a/tests/TestValidateCollection.php +++ b/tests/Test/TestValidateCollection.php @@ -10,7 +10,7 @@ * visited https://www.w7.cc for more details */ -namespace W7\Tests; +namespace W7\Tests\Test; use W7\Tests\Material\TestBaseValidate; diff --git a/tests/TestValidateScene.php b/tests/Test/TestValidateScene.php similarity index 95% rename from tests/TestValidateScene.php rename to tests/Test/TestValidateScene.php index fd3aa19..fb83b28 100644 --- a/tests/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -10,7 +10,7 @@ * visited https://www.w7.cc for more details */ -namespace W7\Tests; +namespace W7\Tests\Test; use W7\Tests\Material\ArticleValidate; use W7\Tests\Material\TestBaseValidate; @@ -72,7 +72,11 @@ class TestValidateScene extends TestBaseValidate $this->expectExceptionMessage('缺少参数:文章Id'); $validate->scene('save')->check($this->userInput); } - + + /** + * @test 测试移除规则 + * @throws ValidateException + */ public function testDynamicScene() { $validate = new ArticleValidate(); -- Gitee From e7eac9ce3a82aa2794311debaffd3ac355f0cf76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 14 Apr 2021 16:24:21 +0800 Subject: [PATCH 047/152] =?UTF-8?q?[D]=20=E5=88=A0=E9=99=A4=E4=B8=AD?= =?UTF-8?q?=E9=97=B4=E4=BB=B6=E4=B8=AD=E7=9A=84ServerRequestInterface?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Event/ValidateEventAbstract.php | 11 ++---- src/Support/Event/ValidateEventInterface.php | 5 +-- src/Support/Event/ValidateResult.php | 38 ------------------- src/Support/Middleware/ValidateMiddleware.php | 8 ++-- src/Support/Storage/ValidateHandler.php | 25 +++++------- src/Validate.php | 33 ++-------------- 6 files changed, 22 insertions(+), 98 deletions(-) delete mode 100644 src/Support/Event/ValidateResult.php diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index d629425..1ac0131 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -13,7 +13,6 @@ namespace W7\Validate\Support\Event; use Closure; -use Psr\Http\Message\ServerRequestInterface; abstract class ValidateEventAbstract implements ValidateEventInterface { @@ -26,25 +25,23 @@ abstract class ValidateEventAbstract implements ValidateEventInterface /** * 场景验证前 * @param array $data 用户输入的数据 - * @param ServerRequestInterface $request * @param Closure $next * @return mixed */ - public function beforeValidate(array $data, ServerRequestInterface $request, Closure $next) + public function beforeValidate(array $data, Closure $next) { - return $next($data, $request); + return $next($data); } /** * 场景验证后 * @param array $data 验证后的数据 - * @param ServerRequestInterface $request * @param Closure $next * @return mixed */ - public function afterValidate(array $data, ServerRequestInterface $request, Closure $next) + public function afterValidate(array $data, Closure $next) { - return $next($data, $request); + return $next($data); } /** diff --git a/src/Support/Event/ValidateEventInterface.php b/src/Support/Event/ValidateEventInterface.php index 6695351..58b05f5 100644 --- a/src/Support/Event/ValidateEventInterface.php +++ b/src/Support/Event/ValidateEventInterface.php @@ -13,10 +13,9 @@ namespace W7\Validate\Support\Event; use Closure; -use Psr\Http\Message\ServerRequestInterface; interface ValidateEventInterface { - public function beforeValidate(array $data, ServerRequestInterface $request, Closure $next); - public function afterValidate(array $data, ServerRequestInterface $request, Closure $next); + public function beforeValidate(array $data, Closure $next); + public function afterValidate(array $data, Closure $next); } diff --git a/src/Support/Event/ValidateResult.php b/src/Support/Event/ValidateResult.php deleted file mode 100644 index e38aa02..0000000 --- a/src/Support/Event/ValidateResult.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Validate\Support\Event; - -use Psr\Http\Message\RequestInterface; - -class ValidateResult -{ - protected array $data; - - protected RequestInterface $request; - - public function __construct(array $data, RequestInterface $request) - { - $this->data = $data; - $this->request = $request; - } - - public function getData(): array - { - return $this->data; - } - - public function getRequest(): RequestInterface - { - return $this->request; - } -} diff --git a/src/Support/Middleware/ValidateMiddleware.php b/src/Support/Middleware/ValidateMiddleware.php index 48b2da4..b7508e6 100644 --- a/src/Support/Middleware/ValidateMiddleware.php +++ b/src/Support/Middleware/ValidateMiddleware.php @@ -27,14 +27,12 @@ class ValidateMiddleware extends MiddlewareAbstract { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - $scene = null; $validator = $this->getValidate($request); if (false === $validator) { $data = []; } else { - $data = array_merge([], $request->getQueryParams(), $request->getParsedBody(), $request->getUploadedFiles()); - $data = $validator->check($data); - $request = $validator->getRequest(); + $data = array_merge([], $request->getQueryParams(), $request->getParsedBody(), $request->getUploadedFiles()); + $data = $validator->check($data); } /** @var Request $request */ @@ -104,7 +102,7 @@ class ValidateMiddleware extends MiddlewareAbstract if (class_exists($validate)) { if (is_subclass_of($validate, Validate::class)) { /** @var Validate $validator */ - $validator = new $validate($request); + $validator = new $validate(); $validator->scene($scene); return $validator; } diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index 558329c..82d6196 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -13,10 +13,8 @@ namespace W7\Validate\Support\Storage; use Closure; -use Psr\Http\Message\RequestInterface; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Event\ValidateEventAbstract; -use W7\Validate\Support\Event\ValidateResult; class ValidateHandler { @@ -24,14 +22,11 @@ class ValidateHandler protected array $data = []; - protected RequestInterface $request; - protected ?string $sceneName = null; - public function __construct(array $data, array $handlers, RequestInterface $request, string $sceneName = null) + public function __construct(array $data, array $handlers, string $sceneName = null) { $this->data = $data; - $this->request = $request; $this->handlers = $handlers; $this->sceneName = $sceneName; } @@ -39,8 +34,8 @@ class ValidateHandler protected function carry(): Closure { return function ($stack, $pipe) { - return function ($data, $request) use ($stack, $pipe) { - return $pipe($data, $request, $stack); + return function ($data) use ($stack, $pipe) { + return $pipe($data, $stack); }; }; } @@ -48,13 +43,13 @@ class ValidateHandler protected function pipes(string $method): array { return array_map(function ($middleware) use ($method) { - return function ($data, $request, $next) use ($middleware, $method) { + return function ($data, $next) use ($middleware, $method) { list($callback, $param) = $middleware; if (class_exists($callback) && is_subclass_of($callback, ValidateEventAbstract::class)) { /** @var ValidateEventAbstract $handler */ $handler = new $callback(...$param); $handler->setSceneName($this->sceneName); - return call_user_func([$handler, $method], $data, $request, $next); + return call_user_func([$handler, $method], $data, $next); } else { throw new ValidateException('Event error or nonexistence'); } @@ -64,8 +59,8 @@ class ValidateHandler protected function destination(): Closure { - return function ($data, $request) { - return new ValidateResult($data, $request); + return function ($data) { + return $data; }; } @@ -75,11 +70,11 @@ class ValidateHandler $pipeline = array_reduce( array_reverse($this->pipes($method)), $this->carry(), - function ($data, $request) use ($destination) { - return $destination($data, $request); + function ($data) use ($destination) { + return $destination($data); } ); - return $pipeline($this->data, $this->request); + return $pipeline($this->data); } } diff --git a/src/Validate.php b/src/Validate.php index 91c1394..5633752 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -19,12 +19,8 @@ use Illuminate\Support\Collection; use Illuminate\Support\Fluent; use Illuminate\Validation\ValidationException; use LogicException; -use Psr\Http\Message\RequestInterface; -use W7\Facade\Context; use W7\Facade\Validator; -use W7\Http\Message\Server\Request; use W7\Validate\Exception\ValidateException; -use W7\Validate\Support\Event\ValidateResult; use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\Storage\ValidateConfig; use W7\Validate\Support\Storage\ValidateHandler; @@ -115,23 +111,12 @@ class Validate */ private array $afters = []; - /** - * Request请求实例 - * @var RequestInterface|null - */ - private ?RequestInterface $request = null; - /** * 当前进行验证的数据 * @var array */ private array $checkData = []; - public function __construct(?RequestInterface $request = null) - { - $this->request = $request; - } - /** * 自动验证 * @param array $data 待验证的数据 @@ -278,28 +263,16 @@ class Validate if (empty($this->handlers)) { return $data; } - $request = $this->request ?: Context::getRequest(); - $request ??= new Request('', null); - $result = (new ValidateHandler($data, $this->handlers, $request, $this->currentScene))->handle($method); + $result = (new ValidateHandler($data, $this->handlers, $this->currentScene))->handle($method); if (is_string($result)) { throw new ValidateException($result, 403); - } elseif ($result instanceof ValidateResult) { - $this->request = $result->getRequest(); - return $result->getData(); + } elseif (is_array($result)) { + return $result; } throw new LogicException('Validate event return type error'); } - /** - * 获取请求类 - * @return RequestInterface|null - */ - public function getRequest(): ?RequestInterface - { - return $this->request; - } - /** * 初始化验证 */ -- Gitee From 5694a8fb7f439403403a761c5610c682a8f0f98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 14 Apr 2021 16:35:24 +0800 Subject: [PATCH 048/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E5=A4=84=E7=90=86=E6=96=B9=E6=B3=95=E5=9C=A8=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E9=AA=8C=E8=AF=81=E5=9C=BA=E6=99=AF=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E4=BD=BF=E7=94=A8=20[F]=20=E4=BF=AE=E5=A4=8D=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95=E4=B8=AD=E4=BA=8B=E4=BB=B6=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Material/HandlerDataValidate.php | 14 +++++++++++- tests/Test/TestHandlerFunction.php | 30 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/Material/HandlerDataValidate.php b/tests/Material/HandlerDataValidate.php index 8d53b28..1f41e54 100644 --- a/tests/Material/HandlerDataValidate.php +++ b/tests/Material/HandlerDataValidate.php @@ -29,6 +29,18 @@ class HandlerDataValidate extends Validate 'beforeSetDefaultNameIsError' => ['name', 'before' => 'setDefaultNameIsError'] ]; + public function sceneBeforeHandlerDataScene() + { + $this->only(['name']) + ->before('setDefaultName'); + } + + public function sceneBeforeSetDefaultNameIsErrorScene() + { + $this->only(['name']) + ->before('setDefaultNameIsError'); + } + public function afterAddData(array $data, $next) { $data['user'][] = 'c'; @@ -48,7 +60,7 @@ class HandlerDataValidate extends Validate public function beforeSetDefaultName(array $data, $next) { - if (isset($data['name']) || empty($data['name'])) { + if (!isset($data['name']) || empty($data['name'])) { $data['name'] = '张三'; } diff --git a/tests/Test/TestHandlerFunction.php b/tests/Test/TestHandlerFunction.php index 3e46d05..f76d79c 100644 --- a/tests/Test/TestHandlerFunction.php +++ b/tests/Test/TestHandlerFunction.php @@ -76,4 +76,34 @@ class TestHandlerFunction extends TestBaseValidate $v->scene('beforeSetDefaultNameIsError')->check([]); } + + /** + * @test 测试在before方法中对值设定一个默认值 - 自定义验证场景 + * @throws \W7\Validate\Exception\ValidateException + */ + public function testBeforeHandlerData2() + { + $v = new HandlerDataValidate(); + + $data = $v->scene('beforeHandlerDataScene')->check([]); + + $this->assertEquals('张三', $data['name']); + + $data = $v->scene('beforeHandlerDataScene')->check(['name' => '李四']); + + $this->assertEquals('李四', $data['name']); + } + + /** + * @test 测试在before方法中对值设定一个不符合规则的默认值 - 自定义验证场景 + * @throws \W7\Validate\Exception\ValidateException + */ + public function testBeforeHandlerToVerifySetDefaultValues2() + { + $v = new HandlerDataValidate(); + + $this->expectExceptionMessage('名称的值只能具有中文'); + + $v->scene('beforeSetDefaultNameIsErrorScene')->check([]); + } } -- Gitee From bf69ae7226ff10828389151926490564dae3413a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 16 Apr 2021 16:22:19 +0800 Subject: [PATCH 049/152] =?UTF-8?q?[U]=20=E5=BD=93=E5=A4=8D=E6=9D=82?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E9=AA=8C=E8=AF=81=E7=9A=84=E9=97=AD=E5=8C=85?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E7=A9=BA=E5=80=BC=E6=97=B6=EF=BC=8C=E7=9B=B4?= =?UTF-8?q?=E6=8E=A5=E5=BF=BD=E7=95=A5=EF=BC=8C=E4=BD=BF=E5=85=B6=E6=96=B9?= =?UTF-8?q?=E4=BE=BF=E5=9C=A8=E9=97=AD=E5=8C=85=E4=B8=AD=E4=BD=BF=E7=94=A8?= =?UTF-8?q?append=EF=BC=8Cremove=E7=AD=89=E6=96=B9=E6=B3=95=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 5633752..7c84fab 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -731,7 +731,7 @@ class Validate } /** - * 加入验证器验证前的方法 + * 添加一个验证前的需要执行的方法 * @param string $callbackName 本类的方法名 * @param mixed ...$params 要传递给方法的参数 * @return $this @@ -743,7 +743,7 @@ class Validate } /** - * 加入验证器验证后的方法 + * 添加一个验证后需要执行的方法 * @param string $callbackName 本类的方法名 * @param mixed ...$params 要传递给方法的参数 * @return $this @@ -850,7 +850,8 @@ class Validate { $data = new Fluent($this->checkData); $result = call_user_func($callback, $data); - if (false === $result) { + + if (false === $result || empty($result)) { return $this; } elseif (true === $result) { $result = $rules; -- Gitee From 01a105dcc4969a74c476e7610ee9e820bcde2bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 16 Apr 2021 16:33:27 +0800 Subject: [PATCH 050/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0addCheckField?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E7=94=A8=E4=BA=8E=E6=B7=BB=E5=8A=A0=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E5=88=B0=E9=AA=8C=E8=AF=81=E5=88=97=E8=A1=A8=E4=B8=AD?= =?UTF-8?q?=20[A]=20=E5=A2=9E=E5=8A=A0removeCheckField=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E5=88=A0=E9=99=A4=E9=AA=8C=E8=AF=81=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E4=B8=AD=E7=9A=84=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Validate.php b/src/Validate.php index 7c84fab..55371ce 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -766,6 +766,28 @@ class Validate return $this; } + /** + * 添加字段到验证列表中 + * @param string $field + * @return $this + */ + public function addCheckField(string $field): Validate + { + $this->checkRule->push($field); + return $this; + } + + /** + * 删除验证列表中的字段 + * @param string $field + * @return $this + */ + public function removeCheckField(string $field): Validate + { + $this->checkRule->pull($field); + return $this; + } + /** * 追加某个字段的验证规则 * -- Gitee From 0da68880aeab56ac92fa0639ec62be928996af98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 16 Apr 2021 17:21:05 +0800 Subject: [PATCH 051/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DaddCheckField,r?= =?UTF-8?q?emoveCheckField=E4=B8=8D=E7=94=9F=E6=95=88=E7=94=9A=E8=87=B3?= =?UTF-8?q?=E5=BC=95=E5=8F=91=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 55371ce..7a36536 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -773,7 +773,8 @@ class Validate */ public function addCheckField(string $field): Validate { - $this->checkRule->push($field); + $rule = $this->rule[$field] ?? ''; + $this->checkRule = $this->checkRule->merge([$field => $rule]); return $this; } @@ -784,7 +785,7 @@ class Validate */ public function removeCheckField(string $field): Validate { - $this->checkRule->pull($field); + $this->checkRule->forget($field); return $this; } -- Gitee From 40e0d260e2942c3404ee7d38737308e69671a596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 19 Apr 2021 14:11:41 +0800 Subject: [PATCH 052/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E4=BC=98=E5=85=88=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 62 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 7a36536..f4dcff7 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -69,6 +69,12 @@ class Validate */ protected bool $filled = true; + /** + * 事件优先 + * @var bool + */ + private bool $eventPriority = true; + /** * 当前验证场景 * @var ?string @@ -128,18 +134,36 @@ class Validate try { $this->checkData = $data; $rule = $this->getSceneRules(); + if ($this->filled) { $rule = $this->addFilledRule($rule); } + if ($this->bail) { $rule = $this->addBailRule($rule); } - $data = $this->handleEvent($data, 'beforeValidate'); - $data = $this->handleCallback($data, 1); + + if ($this->eventPriority) { + $data = $this->handleEvent($data, 'beforeValidate'); + $data = $this->handleCallback($data, 1); + } else { + $data = $this->handleCallback($data, 1); + $data = $this->handleEvent($data, 'beforeValidate'); + } + /** @var \Illuminate\Validation\Validator $v */ $v = Validator::make($data, $rule, $this->message, $this->customAttributes); - $data = $this->handleCallback($v->validate(), 2); - return $this->handleEvent($data, 'afterValidate'); + $data = $v->validate(); + + if ($this->eventPriority) { + $data = $this->handleCallback($data, 2); + $data = $this->handleEvent($data, 'afterValidate'); + } else { + $data = $this->handleEvent($data, 'afterValidate'); + $data = $this->handleCallback($data, 2); + } + + return $data; } catch (ValidationException $e) { $errors = $this->handlingError($e->errors()); $errorMessage = ''; @@ -247,7 +271,7 @@ class Validate } elseif (is_array($data)) { return $data; } - + throw new LogicException('Validate event return type error'); } @@ -278,10 +302,11 @@ class Validate */ private function init() { - $this->checkRule = collect([]); - $this->handlers = []; - $this->afters = []; - $this->befores = []; + $this->checkRule = collect([]); + $this->handlers = []; + $this->afters = []; + $this->befores = []; + $this->eventPriority = true; } /** @@ -718,6 +743,17 @@ class Validate return $this; } + /** + * 设置事件优先级 + * @param bool $priority + * @return $this + */ + public function setEventPriority(bool $priority): Validate + { + $this->eventPriority = $priority; + return $this; + } + /** * 加入事件 * @param string $handler 事件的完整类名,完整命名空间字符串或者加::class @@ -807,7 +843,11 @@ class Validate $appendRule = explode('|', $rule); $this->checkRule[$field] = $this->checkRule[$field]->concat($appendRule); } else { - $this->checkRule[$field] = $this->checkRule[$field] . '|' . $rule; + if (empty($this->checkRule[$field])) { + $this->checkRule[$field] = $rule; + } else { + $this->checkRule[$field] = $this->checkRule[$field] . '|' . $rule; + } } } @@ -970,7 +1010,7 @@ class Validate } else { $this->message = array_merge($this->message, $message); } - + return $this; } -- Gitee From 00936ba36f832893915225dc58c011793dc3af9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 20 Apr 2021 15:08:47 +0800 Subject: [PATCH 053/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0getValidateData?= =?UTF-8?q?=E6=96=B9=E6=B3=95=20[U]=20=E8=B0=83=E6=95=B4sometimes=E9=97=AD?= =?UTF-8?q?=E5=8C=85=E5=86=85=E7=9A=84$data=E4=B8=BAValidateCollection?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index f4dcff7..80d5dfc 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -16,7 +16,6 @@ use Closure; use Illuminate\Contracts\Validation\ImplicitRule; use Illuminate\Support\Arr; use Illuminate\Support\Collection; -use Illuminate\Support\Fluent; use Illuminate\Validation\ValidationException; use LogicException; use W7\Facade\Validator; @@ -185,6 +184,15 @@ class Validate return $this->checkData; } + /** + * 获取当前的验证数据,返回验证集合类型 + * @return Support\Storage\ValidateCollection + */ + public function getValidateData(): Support\Storage\ValidateCollection + { + return validate_collect($this->getData()); + } + /** * 处理错误消息 * @param array $errors @@ -911,7 +919,7 @@ class Validate */ public function sometimes($attribute, $rules, callable $callback): Validate { - $data = new Fluent($this->checkData); + $data = $this->getValidateData(); $result = call_user_func($callback, $data); if (false === $result || empty($result)) { -- Gitee From 494d7e04651b04f7c196aebd1f4fdc73b62d4525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 20 Apr 2021 15:26:36 +0800 Subject: [PATCH 054/152] =?UTF-8?q?[A]=20=E9=AA=8C=E8=AF=81=E5=99=A8?= =?UTF-8?q?=E9=9B=86=E5=90=88=E5=A2=9E=E5=8A=A0=5F=5Fget=EF=BC=8C=5F=5Fset?= =?UTF-8?q?=E9=AD=94=E6=B3=95=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 9f38945..5fd2356 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -281,4 +281,18 @@ class ValidateCollection extends Collection Arr::set($this->items, $key, $value); return $this; } + + public function __get($key) + { + if (array_key_exists($key, $this->items)) { + return $this->offsetGet($key); + } + + return parent::get($key); + } + + public function __set($key, $value) + { + $this->offsetSet($key, $value); + } } -- Gitee From 2907197bb301d917da04a7a1a80fa2e2d86469d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 20 Apr 2021 15:30:27 +0800 Subject: [PATCH 055/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7482d17..1d81397 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,14 @@ ## 说明 此验证基于Laravel的Validator验证器,做了如下改变 - - 可通过类的方式定义一个[验证器](https://v.neww7.com/Validate.htm) + - 可通过类的方式定义一个[验证器](https://v.neww7.com/Validate.html) - 增加[验证场景](https://v.neww7.com/Scene.html) - 增加[场景事件处理](https://v.neww7.com/Event.html) - 修改了[自定义验证规则](https://v.neww7.com/Rule.html) + - [自定义消息](https://v.neww7.com/Message.html) 增加了对内容的引用 + - 继承集合类增加一个[验证集合](https://v.neww7.com/Collection.html) -等... +等...使您的验证只需要在验证器中全部都可以完成 > 此文档只说明与Laravel的Validator验证器不同的地方,完整Laravel Validator文档可查看:[完整文档](https://learnku.com/docs/laravel/6.x/validation/5144) -- Gitee From e9d8c26eef59d4fda4e8acdf4c56b6faeb6037d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 21 Apr 2021 11:30:55 +0800 Subject: [PATCH 056/152] =?UTF-8?q?[U]=20=E4=BD=BFsometimes=E8=81=8C?= =?UTF-8?q?=E8=B4=A3=E5=8D=95=E4=B8=80=E5=8C=96=EF=BC=8C=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E9=97=AD=E5=8C=85=E8=BF=94=E5=9B=9E=E5=8F=AA=E5=8F=AF=E8=BF=94?= =?UTF-8?q?=E5=9B=9EBool=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 2 +- src/Validate.php | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 5fd2356..8f94ad7 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -288,7 +288,7 @@ class ValidateCollection extends Collection return $this->offsetGet($key); } - return parent::get($key); + return parent::__get($key); } public function __set($key, $value) diff --git a/src/Validate.php b/src/Validate.php index 80d5dfc..9395f55 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -21,6 +21,7 @@ use LogicException; use W7\Facade\Validator; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Rule\BaseRule; +use W7\Validate\Support\Storage\ValidateCollection; use W7\Validate\Support\Storage\ValidateConfig; use W7\Validate\Support\Storage\ValidateHandler; @@ -914,7 +915,8 @@ class Validate * * @param string|string[] $attribute 字段 * @param string|array|BaseRule $rules 规则 - * @param callable $callback 回调方法,返回true获取具体规则生效 + * @param callable $callback 回调方法,方法提供一个{@see ValidateCollection} $data参数,参数为当前验证的数据, + * 返回true则规则生效 * @return $this */ public function sometimes($attribute, $rules, callable $callback): Validate @@ -922,22 +924,20 @@ class Validate $data = $this->getValidateData(); $result = call_user_func($callback, $data); - if (false === $result || empty($result)) { + if (!$result) { return $this; - } elseif (true === $result) { - $result = $rules; } - if (is_array($result)) { - $result = implode('|', $result); + if (is_array($rules)) { + $rules = implode('|', $rules); } if (is_array($attribute)) { foreach ($attribute as $filed) { - $this->append($filed, $result); + $this->append($filed, $rules); } } else { - $this->append($attribute, $result); + $this->append($attribute, $rules); } return $this; -- Gitee From 5649bfa856897ce730a72f72b38126f3c53f0a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 21 Apr 2021 15:38:10 +0800 Subject: [PATCH 057/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DGet=E5=9C=A8?= =?UTF-8?q?=E4=BD=BF=E7=94=A8*=E8=8E=B7=E5=8F=96=E5=A4=9A=E9=87=8D?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E7=9A=84=E6=95=B0=E6=8D=AE=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 51 ++++++++++++++-------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 8f94ad7..cabd6fc 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -17,6 +17,7 @@ use Closure; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\HigherOrderWhenProxy; +use Illuminate\Support\Str; use W7\Validate\Exception\CollectionException; class ValidateCollection extends Collection @@ -183,29 +184,43 @@ class ValidateCollection extends Collection public function get($key, $default = null) { if (false !== strpos($key, '*')) { - $_value = explode('.', $key); - $_data = $this->items; - - while (false !== ($index = array_search('*', $_value))) { - $_key = array_slice($_value, 0, $index); - $_pluckKey = array_slice($_value, $index + 1, 1); - $_value = array_slice($_value, $index + 2); - - if (empty($_key)) { - $_data = Arr::pluck($_data, $_pluckKey); - } else { - $_data = Arr::pluck(Arr::get($_data, implode('.', $_key)), $_pluckKey); - } + $explicitPath = rtrim(explode('*', $key)[0], '.') ?: null; + $results = []; + $_default = rand(1e+5, 1e+10) . time(); + $_value = Arr::get($this->items, $explicitPath, $_default); + + if ($_default !== $_value) { + Arr::set($results, $explicitPath, $_value); } - if (!empty($_value)) { - $_value = implode(',', $_value); - $_data = Arr::get($_data, $_value); + if (! Str::contains($key, '*') || Str::endsWith($key, '*')) { + $value = Arr::get($this->items, $key); + } else { + data_set($results, $key, null, true); + + $results = Arr::dot($results); + + $keys = []; + + $pattern = str_replace('\*', '[^\.]+', preg_quote($key)); + + foreach ($results as $_key => $_value) { + if (preg_match('/^' . $pattern . '/', $_key, $matches)) { + $keys[] = $matches[0]; + } + } + + $value = []; + $keys = array_unique($keys); + + foreach ($keys as $key) { + $value[] = Arr::get($this->items, $key); + } } - $value = $_data ?: ($default instanceof Closure ? $default() : $default); + $value = $value ?: value($default); } elseif (false !== strpos($key, '.')) { - $value = Arr::get($this->items, $key, $default instanceof Closure ? $default() : $default); + $value = Arr::get($this->items, $key, $default); } else { $value = parent::get($key, $default); } -- Gitee From 3a879409f0fbbc6560f1a59015325e96bc44bc05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 21 Apr 2021 19:12:26 +0800 Subject: [PATCH 058/152] =?UTF-8?q?[U]=20=E9=A1=B9=E7=9B=AE=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E6=94=B9=E4=B8=BAilluminate/validation=20[U]=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=A1=B9=E7=9B=AE=E7=9A=84=E9=85=8D=E7=BD=AE?= =?UTF-8?q?ValidateConfig=20[U]=20=E4=BF=AE=E6=94=B9=E8=BD=AF=E6=93=8E?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E4=B8=AD=E9=97=B4=E4=BB=B6=E7=9A=84=E5=91=BD?= =?UTF-8?q?=E5=90=8D=E7=A9=BA=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- .../{ => Rangine}/ValidateMiddleware.php | 2 +- src/Support/Storage/ValidateConfig.php | 163 +++++++++++++++++- src/Validate.php | 20 ++- tests/Material/ArticleValidate.php | 10 +- tests/Material/HandlerDataValidate.php | 4 + tests/Material/TestBaseValidate.php | 15 +- 7 files changed, 194 insertions(+), 22 deletions(-) rename src/Support/Middleware/{ => Rangine}/ValidateMiddleware.php (98%) diff --git a/composer.json b/composer.json index 726f7c2..f80457c 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^7.4|^8.0", - "w7/rangine": "^v2.4.10" + "illuminate/validation": "^6.0|^7.0|^8.0" }, "require-dev": { "phpunit/phpunit" : "^9.5", diff --git a/src/Support/Middleware/ValidateMiddleware.php b/src/Support/Middleware/Rangine/ValidateMiddleware.php similarity index 98% rename from src/Support/Middleware/ValidateMiddleware.php rename to src/Support/Middleware/Rangine/ValidateMiddleware.php index b7508e6..b6c9ec1 100644 --- a/src/Support/Middleware/ValidateMiddleware.php +++ b/src/Support/Middleware/Rangine/ValidateMiddleware.php @@ -10,7 +10,7 @@ * visited https://www.w7.cc for more details */ -namespace W7\Validate\Support\Middleware; +namespace W7\Validate\Support\Middleware\Rangine; use Exception; use Psr\Http\Message\ResponseInterface; diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 2c8cd9a..b863fb1 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -12,12 +12,18 @@ namespace W7\Validate\Support\Storage; -use W7\Core\Helper\Traiter\InstanceTraiter; +use Composer\Autoload\ClassLoader; +use Illuminate\Contracts\Container\Container; +use Illuminate\Contracts\Translation\Translator; +use Illuminate\Filesystem\Filesystem; +use Illuminate\Support\Facades\App; +use Illuminate\Translation\FileLoader; +use Illuminate\Validation\Factory; +use Illuminate\Validation\PresenceVerifierInterface; +use W7\Contract\Validation\ValidatorFactoryInterface; -class ValidateConfig +final class ValidateConfig { - use InstanceTraiter; - /** * 自定义规则命名空间前缀 * @var array @@ -30,12 +36,161 @@ class ValidateConfig */ protected array $autoValidatePath = []; + /** + * 翻译器 + * @var Translator + */ + protected Translator $translator; + + /** + * 容器 + * @var Container + */ + protected Container $container; + + /** + * 验证器工厂 + * @var Factory + */ + protected Factory $factory; + + /** + * 存在验证器 + * @var PresenceVerifierInterface + */ + protected PresenceVerifierInterface $verifier; + /** * 验证器具体关联 * @var array */ protected array $validateLink = []; + protected static ValidateConfig $instance; + + public static function instance(): ValidateConfig + { + if (empty(self::$instance)) { + self::$instance = new ValidateConfig(); + } + + return self::$instance; + } + + /** + * 设置框架类型 + * @param int $type 1 Laravel 2 Rangine + */ + public function setFramework(int $type): ValidateConfig + { + switch ($type) { + case 1: + $factory = App::make('validator'); + break; + case 2: + $factory = \W7\Facade\Container::singleton(ValidatorFactoryInterface::class); + break; + default: + throw new \RuntimeException('Framework Type Error'); + } + + return $this->setFactory($factory); + } + + /** + * 提供翻译器 + * @param Translator $translator + * @return $this + */ + public function setTranslator(Translator $translator): ValidateConfig + { + $this->translator = $translator; + return $this; + } + + /** + * 设置验证器工厂 + * @param Factory $factory + * @return ValidateConfig + */ + public function setFactory(Factory $factory): ValidateConfig + { + $this->factory = $factory; + return $this; + } + + /** + * 获取验证器工厂 + * @return Factory + */ + public function getFactory(): Factory + { + if (empty($this->factory)) { + $this->factory = new Factory($this->getTranslator(), $this->getContainer()); + if ($this->getPresenceVerifier()) { + $this->factory->setPresenceVerifier($this->getPresenceVerifier()); + } + } + + return $this->factory; + } + + /** + * 设置存在验证器的实现。 + * @param PresenceVerifierInterface $presenceVerifier + * @return $this + */ + public function setPresenceVerifier(PresenceVerifierInterface $presenceVerifier): ValidateConfig + { + $this->verifier = $presenceVerifier; + return $this; + } + + /** + * 提供容器 + * @param Container $container + * @return ValidateConfig + */ + public function setContainer(Container $container): ValidateConfig + { + $this->container = $container; + return $this; + } + + /** + * 获取存在验证器 + * @return PresenceVerifierInterface|null + */ + private function getPresenceVerifier(): ?PresenceVerifierInterface + { + return $this->verifier ?? null; + } + + /** + * 获取容器 + * @return Container|null + */ + private function getContainer(): ?Container + { + return $this->container ?? null; + } + + /** + * 获取翻译器 + * @return Translator + */ + private function getTranslator(): Translator + { + if (empty($this->translator)) { + $reflection = new \ReflectionClass(ClassLoader::class); + $vendorDir = dirname($reflection->getFileName(), 2); + $loader = new FileLoader(new Filesystem(), $vendorDir); + return new \Illuminate\Translation\Translator($loader, 'zh_CN'); + } + + return $this->translator; + } + /** * 设置自动加载验证器规则 * @param string $controllerPath 控制器路径 diff --git a/src/Validate.php b/src/Validate.php index 9395f55..d2497d4 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -16,9 +16,9 @@ use Closure; use Illuminate\Contracts\Validation\ImplicitRule; use Illuminate\Support\Arr; use Illuminate\Support\Collection; +use Illuminate\Validation\Factory; use Illuminate\Validation\ValidationException; use LogicException; -use W7\Facade\Validator; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\Storage\ValidateCollection; @@ -123,6 +123,15 @@ class Validate */ private array $checkData = []; + /** + * 获取验证器工厂 + * @return Factory + */ + private static function getValidationFactory(): Factory + { + return ValidateConfig::instance()->getFactory(); + } + /** * 自动验证 * @param array $data 待验证的数据 @@ -151,8 +160,7 @@ class Validate $data = $this->handleEvent($data, 'beforeValidate'); } - /** @var \Illuminate\Validation\Validator $v */ - $v = Validator::make($data, $rule, $this->message, $this->customAttributes); + $v = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes); $data = $v->validate(); if ($this->eventPriority) { @@ -172,7 +180,7 @@ class Validate break; } - throw new ValidateException($errorMessage, 403, $errors); + throw new ValidateException($errorMessage, 403, $errors, $e); } } @@ -721,7 +729,7 @@ class Validate self::$implicitRules[] = $ruleName; } - Validator::$method($ruleName, $extension, $message); + self::getValidationFactory()->$method($ruleName, $extension, $message); } /** @@ -737,7 +745,7 @@ class Validate $rule = $ruleName; } } - Validator::replacer($rule, $replacer); + self::getValidationFactory()->replacer($rule, $replacer); } /** diff --git a/tests/Material/ArticleValidate.php b/tests/Material/ArticleValidate.php index d83136c..edfccf9 100644 --- a/tests/Material/ArticleValidate.php +++ b/tests/Material/ArticleValidate.php @@ -19,7 +19,7 @@ class ArticleValidate extends Validate protected array $rule = [ 'id' => 'required|numeric', 'content' => 'required|between:1,2000', - 'title' => 'required|between:4,50|alpha', + 'title' => 'required|between:4,50|alpha|checkTitle', 'type' => 'required|numeric', ]; @@ -33,6 +33,7 @@ class ArticleValidate extends Validate 'title.alpha' => '文章标题长度为4~50个字符', 'type.required' => '文章分类必须填写', 'type.numeric' => '文章分类错误', + 'title.checkTitle' => '有错误啦' ]; protected array $scene = [ @@ -40,7 +41,12 @@ class ArticleValidate extends Validate 'save' => ['use' => 'edit'], 'del' => ['id'], ]; - + + public function ruleCheckTitle() + { + return true; + } + public function sceneEdit() { return $this->only(['id', 'content', 'title']) diff --git a/tests/Material/HandlerDataValidate.php b/tests/Material/HandlerDataValidate.php index 1f41e54..f70e024 100644 --- a/tests/Material/HandlerDataValidate.php +++ b/tests/Material/HandlerDataValidate.php @@ -22,6 +22,10 @@ class HandlerDataValidate extends Validate 'name' => 'required|Chs' ]; + protected array $customAttributes = [ + 'name' => '名称' + ]; + protected array $scene = [ 'afterRule' => ['user', 'user.*', 'after' => 'checkUserNotRepeat'], 'addData' => ['user', 'user.*', 'after' => 'addData'], diff --git a/tests/Material/TestBaseValidate.php b/tests/Material/TestBaseValidate.php index bfe4c8b..6daaf47 100644 --- a/tests/Material/TestBaseValidate.php +++ b/tests/Material/TestBaseValidate.php @@ -12,6 +12,9 @@ namespace W7\Tests\Material; +use Illuminate\Filesystem\Filesystem; +use Illuminate\Translation\FileLoader; +use Illuminate\Translation\Translator; use PHPUnit\Framework\TestCase; use W7\Validate\Support\Storage\ValidateConfig; @@ -19,16 +22,12 @@ class TestBaseValidate extends TestCase { public function __construct($name = null, array $data = [], $dataName = '') { - $this->rangineInit(); + $loader = new FileLoader(new Filesystem(), dirname(__DIR__, 2)); + $translator = new Translator($loader, 'zh_CN'); + + ValidateConfig::instance()->setTranslator($translator); ValidateConfig::instance()->setRulesPath('W7\\Tests\\Material\\Rules\\'); parent::__construct($name, $data, $dataName); } - - private function rangineInit() - { - !defined('BASE_PATH') && define('BASE_PATH', dirname(__DIR__, 2)); - !defined('APP_PATH') && define('APP_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'app'); - !defined('RUNTIME_PATH') && define('RUNTIME_PATH', BASE_PATH . DIRECTORY_SEPARATOR . 'runtime'); - } } -- Gitee From ae76bedc282376ec2b700927bd970b6700256f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 21 Apr 2021 19:14:28 +0800 Subject: [PATCH 059/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d81397..c70ff1f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # 软擎验证扩展 ## 说明 -此验证基于Laravel的Validator验证器,做了如下改变 +此验证基于Laravel的Validator验证器,可用于Laravel,软擎等依赖于illuminate/validation的项目中,此验证器做了如下扩展: + - 可通过类的方式定义一个[验证器](https://v.neww7.com/Validate.html) - 增加[验证场景](https://v.neww7.com/Scene.html) - 增加[场景事件处理](https://v.neww7.com/Event.html) -- Gitee From 611997c8b8a2f8fa4a54619fbfb31e7d6510f961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 22 Apr 2021 13:58:18 +0800 Subject: [PATCH 060/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0Laravel?= =?UTF-8?q?=E7=9A=84=E9=AA=8C=E8=AF=81=E4=B8=AD=E9=97=B4=E4=BB=B6=20[F]=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=AD=E9=97=B4=E4=BB=B6=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8F=91=E7=8E=B0=E5=9C=A8=E7=89=B9=E5=AE=9A=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E4=B8=8B=E5=87=BA=E7=8E=B0=E5=8F=91=E7=8E=B0=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Middleware/Laravel/ValidateMiddleware.php | 34 +++++++ .../Middleware/Rangine/ValidateMiddleware.php | 94 +++---------------- src/Support/Storage/ValidateConfig.php | 85 ++++++++++------- src/Support/Storage/ValidateFactory.php | 82 ++++++++++++++++ src/Support/helpers.php | 17 ++-- 5 files changed, 193 insertions(+), 119 deletions(-) create mode 100644 src/Support/Middleware/Laravel/ValidateMiddleware.php create mode 100644 src/Support/Storage/ValidateFactory.php diff --git a/src/Support/Middleware/Laravel/ValidateMiddleware.php b/src/Support/Middleware/Laravel/ValidateMiddleware.php new file mode 100644 index 0000000..2ba43b4 --- /dev/null +++ b/src/Support/Middleware/Laravel/ValidateMiddleware.php @@ -0,0 +1,34 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Middleware\Laravel; + +use Closure; +use Illuminate\Http\Request; +use W7\Validate\Support\Storage\ValidateFactory; + +class ValidateMiddleware +{ + public function handle(Request $request, Closure $next) + { + list($controller, $scene) = explode('@', $request->route()->getActionName()); + + $validator = ValidateFactory::getValidate($controller, $scene); + + if ($validator) { + $data = $validator->check($request->all()); + $request->offsetSet('__validate__data__', $data); + } + + return $next($request); + } +} diff --git a/src/Support/Middleware/Rangine/ValidateMiddleware.php b/src/Support/Middleware/Rangine/ValidateMiddleware.php index b6c9ec1..aa3912c 100644 --- a/src/Support/Middleware/Rangine/ValidateMiddleware.php +++ b/src/Support/Middleware/Rangine/ValidateMiddleware.php @@ -12,7 +12,6 @@ namespace W7\Validate\Support\Middleware\Rangine; -use Exception; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; @@ -20,95 +19,32 @@ use W7\Core\Route\Route; use W7\Facade\Context; use W7\Core\Middleware\MiddlewareAbstract; use W7\Http\Message\Server\Request; -use W7\Validate\Support\Storage\ValidateConfig; -use W7\Validate\Validate; +use W7\Validate\Support\Storage\ValidateFactory; class ValidateMiddleware extends MiddlewareAbstract { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - { - $validator = $this->getValidate($request); - if (false === $validator) { - $data = []; - } else { - $data = array_merge([], $request->getQueryParams(), $request->getParsedBody(), $request->getUploadedFiles()); - $data = $validator->check($data); - } - - /** @var Request $request */ - $request = $request->withAttribute('validate', $data); - Context::setRequest($request); - return $handler->handle($request); - } - - final public function getValidate(ServerRequestInterface $request) { /** @var Route $route */ - $route = $request->getAttribute('route'); - $handler = $route->handler; - if (!is_array($handler) || 2 !== count($handler)) { - return false; - } - $controller = $handler[0] ?? ''; - $scene = $handler[1] ?? ''; - $haveLink = false; - $validate = ''; - - $validateLink = ValidateConfig::instance()->getValidateLink($controller); - if (!empty($validateLink)) { - # 为指定的控制器方法指定了验证器 - if (isset($validateLink[$scene]) || isset($validateLink['!__other__'])) { - if (isset($validateLink['!__other__'])) { - $method = '!__other__'; - } else { - $method = $scene; - } + $route = $request->getAttribute('route'); + $routeHandler = $route->handler; - # 为指定的验证器指定了验证场景 - if (is_array($validateLink[$method])) { - if (count($validateLink[$method]) >= 2) { - $validate = $validateLink[$method][0]; - $scene = $validateLink[$method][1]; - $haveLink = true; - } - } else { - $validate = $validateLink[$method]; - $haveLink = true; - } - } + if (!is_array($routeHandler) || 2 !== count($routeHandler)) { + throw new \RuntimeException('Routing information retrieval failed'); } - if (false === $haveLink) { - # 处理指定了路径的控制器 - $controllerPath = ''; - $validatePath = ''; - foreach (ValidateConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { - if (false !== strpos($controller, $_controllerPath)) { - $controllerPath = $_controllerPath; - $validatePath = $_validatePath; - break; - } - } - if (empty($controllerPath)) { - return false; - } - - $validate = str_replace($controllerPath, '', $controller); - $_namespace = explode('\\', $validate); - $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); - $validate = $validatePath . implode('\\', $_namespace) . '\\' . $fileName; - } + list($controller, $scene) = $routeHandler; - if (class_exists($validate)) { - if (is_subclass_of($validate, Validate::class)) { - /** @var Validate $validator */ - $validator = new $validate(); - $validator->scene($scene); - return $validator; - } + $validator = ValidateFactory::getValidate($controller, $scene); - throw new Exception("The given 'Validate' " . $validate . ' has to be a subtype of W7\Validate\Validate'); + if ($validator) { + $data = array_merge([], $request->getQueryParams(), $request->getParsedBody(), $request->getUploadedFiles()); + $data = $validator->check($data); + /** @var Request $request */ + $request = $request->withAttribute('__validate__data__', $data); + Context::setRequest($request); } - return false; + + return $handler->handle($request); } } diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index b863fb1..fe7689d 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -20,7 +20,6 @@ use Illuminate\Support\Facades\App; use Illuminate\Translation\FileLoader; use Illuminate\Validation\Factory; use Illuminate\Validation\PresenceVerifierInterface; -use W7\Contract\Validation\ValidatorFactoryInterface; final class ValidateConfig { @@ -60,6 +59,13 @@ final class ValidateConfig */ protected PresenceVerifierInterface $verifier; + /** + * 框架类型 + * 1 Laravel 2 Rangine + * @var int + */ + protected int $framework = 0; + /** * 验证器具体关联 * @var array @@ -83,28 +89,7 @@ final class ValidateConfig */ public function setFramework(int $type): ValidateConfig { - switch ($type) { - case 1: - $factory = App::make('validator'); - break; - case 2: - $factory = \W7\Facade\Container::singleton(ValidatorFactoryInterface::class); - break; - default: - throw new \RuntimeException('Framework Type Error'); - } - - return $this->setFactory($factory); - } - - /** - * 提供翻译器 - * @param Translator $translator - * @return $this - */ - public function setTranslator(Translator $translator): ValidateConfig - { - $this->translator = $translator; + $this->framework = $type; return $this; } @@ -126,9 +111,22 @@ final class ValidateConfig public function getFactory(): Factory { if (empty($this->factory)) { - $this->factory = new Factory($this->getTranslator(), $this->getContainer()); - if ($this->getPresenceVerifier()) { - $this->factory->setPresenceVerifier($this->getPresenceVerifier()); + if ($this->framework > 0) { + switch ($this->framework) { + case 1: + $this->factory = App::make('validator'); + break; + case 2: + $this->factory = \W7\Facade\Container::singleton(ValidatorFactoryInterface::class); + break; + default: + throw new \RuntimeException('Framework Type Error'); + } + } else { + $this->factory = new Factory($this->getTranslator(), $this->getContainer()); + if ($this->getPresenceVerifier()) { + $this->factory->setPresenceVerifier($this->getPresenceVerifier()); + } } } @@ -146,6 +144,15 @@ final class ValidateConfig return $this; } + /** + * 获取存在验证器 + * @return PresenceVerifierInterface|null + */ + private function getPresenceVerifier(): ?PresenceVerifierInterface + { + return $this->verifier ?? null; + } + /** * 提供容器 * @param Container $container @@ -158,21 +165,23 @@ final class ValidateConfig } /** - * 获取存在验证器 - * @return PresenceVerifierInterface|null + * 获取容器 + * @return Container|null */ - private function getPresenceVerifier(): ?PresenceVerifierInterface + private function getContainer(): ?Container { - return $this->verifier ?? null; + return $this->container ?? null; } /** - * 获取容器 - * @return Container|null + * 提供翻译器 + * @param Translator $translator + * @return $this */ - private function getContainer(): ?Container + public function setTranslator(Translator $translator): ValidateConfig { - return $this->container ?? null; + $this->translator = $translator; + return $this; } /** @@ -199,6 +208,14 @@ final class ValidateConfig */ public function setAutoValidatePath(string $controllerPath, string $validatePath): ValidateConfig { + if ('\\' !== substr($controllerPath, -1)) { + $controllerPath = $controllerPath . '\\'; + } + + if ('\\' !== substr($validatePath, -1)) { + $validatePath = $validatePath . '\\'; + } + $this->autoValidatePath[$controllerPath] = $validatePath; return $this; } diff --git a/src/Support/Storage/ValidateFactory.php b/src/Support/Storage/ValidateFactory.php new file mode 100644 index 0000000..d3729dd --- /dev/null +++ b/src/Support/Storage/ValidateFactory.php @@ -0,0 +1,82 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Storage; + +use Exception; +use W7\Validate\Validate; + +class ValidateFactory +{ + public static function getValidate(string $controller, string $scene = '') + { + $haveLink = false; + $validate = ''; + + $validateLink = ValidateConfig::instance()->getValidateLink($controller); + if (!empty($validateLink)) { + # 为指定的控制器方法指定了验证器 + if (isset($validateLink[$scene]) || isset($validateLink['!__other__'])) { + if (isset($validateLink['!__other__'])) { + $method = '!__other__'; + } else { + $method = $scene; + } + + # 为指定的验证器指定了验证场景 + if (is_array($validateLink[$method])) { + if (count($validateLink[$method]) >= 2) { + $validate = $validateLink[$method][0]; + $scene = $validateLink[$method][1]; + $haveLink = true; + } + } else { + $validate = $validateLink[$method]; + $haveLink = true; + } + } + } + + if (false === $haveLink) { + # 处理指定了路径的控制器 + $controllerPath = ''; + $validatePath = ''; + foreach (ValidateConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { + if (false !== strpos($controller, $_controllerPath)) { + $controllerPath = $_controllerPath; + $validatePath = $_validatePath; + break; + } + } + if (empty($controllerPath)) { + return false; + } + + $validate = str_replace($controllerPath, '', $controller); + $_namespace = explode('\\', $validate); + $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); + $validate = $validatePath . (empty($_namespace) ? implode('\\', $_namespace) . '\\' : '') . $fileName; + } + + if (class_exists($validate)) { + if (is_subclass_of($validate, Validate::class)) { + /** @var Validate $validator */ + $validator = new $validate(); + $validator->scene($scene); + return $validator; + } + + throw new Exception("The given 'Validate' " . $validate . ' has to be a subtype of W7\Validate\Validate'); + } + return false; + } +} diff --git a/src/Support/helpers.php b/src/Support/helpers.php index 89c73d4..a29ece7 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -11,7 +11,7 @@ */ use Psr\Http\Message\ServerRequestInterface; -use W7\Facade\Context; +use Illuminate\Http\Request; use W7\Validate\Support\Storage\ValidateCollection; if (!function_exists('validate_collect')) { @@ -29,14 +29,19 @@ if (!function_exists('validate_collect')) { if (!function_exists('get_validate_data')) { /** * 获取验证后的结果 - * @param ServerRequestInterface|null $request 请求示例,如果为null,则自动从上下文中获取 + * @param ServerRequestInterface|Request $request 请求示例 * @return ValidateCollection 返回验证器集合ValidateCollection类型 */ - function get_validate_data(ServerRequestInterface $request = null): ValidateCollection + function get_validate_data($request = null): ValidateCollection { - if (null === $request) { - $request = Context::getRequest(); + if ($request instanceof ServerRequestInterface) { + $data = $request->getAttribute('__validate__data__'); + } elseif ($request instanceof Request) { + $data = $request->offsetGet('__validate__data__'); + } else { + $data = []; } - return validate_collect($request->getAttribute('validate')); + + return validate_collect($data); } } -- Gitee From 8be4d8a9c003c7f60ed654a7e50d10ac304b7269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 22 Apr 2021 14:21:09 +0800 Subject: [PATCH 061/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E8=BD=AF?= =?UTF-8?q?=E6=93=8E=E6=A1=86=E6=9E=B6=E4=B8=AD=E6=97=A0=E6=B3=95=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=88=9B=E5=BB=BA=E9=AA=8C=E8=AF=81=E5=99=A8=E5=B7=A5?= =?UTF-8?q?=E5=8E=82=E7=9A=84=E9=97=AE=E9=A2=98=20[F]=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=B8=AD=E9=97=B4=E4=BB=B6=E6=89=BE=E4=B8=8D=E5=88=B0=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=99=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateConfig.php | 2 +- src/Support/Storage/ValidateFactory.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index fe7689d..4efb9fb 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -117,7 +117,7 @@ final class ValidateConfig $this->factory = App::make('validator'); break; case 2: - $this->factory = \W7\Facade\Container::singleton(ValidatorFactoryInterface::class); + $this->factory = \W7\Facade\Container::singleton("W7\Contract\Validation\ValidatorFactoryInterface"); break; default: throw new \RuntimeException('Framework Type Error'); diff --git a/src/Support/Storage/ValidateFactory.php b/src/Support/Storage/ValidateFactory.php index d3729dd..b8ae91b 100644 --- a/src/Support/Storage/ValidateFactory.php +++ b/src/Support/Storage/ValidateFactory.php @@ -64,7 +64,7 @@ class ValidateFactory $validate = str_replace($controllerPath, '', $controller); $_namespace = explode('\\', $validate); $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); - $validate = $validatePath . (empty($_namespace) ? implode('\\', $_namespace) . '\\' : '') . $fileName; + $validate = $validatePath . (!empty($_namespace) ? implode('\\', $_namespace) . '\\' : '') . $fileName; } if (class_exists($validate)) { -- Gitee From 649ef8d6aaaa367362b78f6fe4a6e7e31b37ccb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 26 Apr 2021 14:36:24 +0800 Subject: [PATCH 062/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E6=98=AF=E7=B1=BB=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E5=B9=B6=E6=90=BA=E5=B8=A6=E5=8F=82=E6=95=B0=E6=97=B6?= =?UTF-8?q?=E8=A7=84=E5=88=99=E4=B8=8D=E7=94=9F=E6=95=88=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20[F]=20=E4=BF=AE=E5=A4=8D=E9=AA=8C=E8=AF=81=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E4=BA=8B=E4=BB=B6=E5=92=8CUse=E5=9C=A8?= =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E6=AC=A1=E8=B0=83=E7=94=A8=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateHandler.php | 14 +--- src/Validate.php | 29 +++++--- ...tBaseValidate.php => BaseTestValidate.php} | 2 +- tests/Material/Event/Increasing.php | 32 +++++++++ tests/Material/Event/SetDefault.php | 32 +++++++++ tests/Material/HandlerEventValidate.php | 43 ++++++++++++ tests/Test/TestHandlerEvent.php | 70 +++++++++++++++++++ tests/Test/TestHandlerFunction.php | 4 +- tests/Test/TestValidateCollection.php | 4 +- tests/Test/TestValidateScene.php | 4 +- 10 files changed, 204 insertions(+), 30 deletions(-) rename tests/Material/{TestBaseValidate.php => BaseTestValidate.php} (95%) create mode 100644 tests/Material/Event/Increasing.php create mode 100644 tests/Material/Event/SetDefault.php create mode 100644 tests/Material/HandlerEventValidate.php create mode 100644 tests/Test/TestHandlerEvent.php diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index 82d6196..a38116f 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -57,22 +57,12 @@ class ValidateHandler }, $this->handlers); } - protected function destination(): Closure - { - return function ($data) { - return $data; - }; - } - public function handle(string $method) { - $destination = $this->destination(); - $pipeline = array_reduce( + $pipeline = array_reduce( array_reverse($this->pipes($method)), $this->carry(), - function ($data) use ($destination) { - return $destination($data); - } + fn ($data) => $data ); return $pipeline($this->data); diff --git a/src/Validate.php b/src/Validate.php index d2497d4..58402c1 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -355,11 +355,7 @@ class Validate return $ruleClass; } - if (method_exists($this, 'rule' . ucfirst($value))) { - self::extend($value, Closure::fromCallable([$this, 'rule' . ucfirst($value)])); - } - - return $this->getExtendsName($value, $field); + return $this->getExtendsRule($value, $field); } return $value; }); @@ -369,13 +365,13 @@ class Validate } /** - * 获取扩展方法的名称 + * 获取扩展规则 * 由于为了区分多个验证器的相同自定义方法名,对方法名做了处理,此方法为了使规则和处理后的方法名对应上 * @param string $rule 规则名称 * @param string|null $field 字段 * @return string */ - private function getExtendsName(string $rule, string $field = null): string + private function getExtendsRule(string $rule, string $field = null): string { list($rule, $param) = $this->getKeyAndParam($rule, false); @@ -388,6 +384,18 @@ class Validate } $rule = $ruleName; + } else { + # 如果当前自定义规则中不存在,则判断是否为类方法 + # 如果是类方法,则先注册规则到验证器中,然后再处理对应的错误消息 + if (method_exists($this, 'rule' . ucfirst($rule))) { + self::extend($rule, Closure::fromCallable([$this, 'rule' . ucfirst($rule)])); + + if ('' !== $param) { + $rule = $rule . ':' . $param; + } + + return $this->getExtendsRule($rule, $field); + } } if ('' !== $param) { @@ -585,7 +593,6 @@ class Validate $handlers = $sceneRule['handler']; $this->addHandler($handlers); unset($sceneRule['handler']); - unset($this->scene[$name]['handler']); } # 判断是否定义了验证前需要执行的方法 @@ -593,7 +600,6 @@ class Validate $callback = $sceneRule['before']; $this->addBefore($callback); unset($sceneRule['before']); - unset($this->scene[$name]['before']); } # 判断是否定义了验证后需要执行的方法 @@ -601,14 +607,15 @@ class Validate $callback = $sceneRule['after']; $this->addAfter($callback); unset($sceneRule['after']); - unset($this->scene[$name]['after']); } # 判断验证场景是否指定了其他验证场景 if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { $use = $sceneRule['use']; + if ($use === $name || $use === $this->currentScene) { + throw new LogicException('The scene used cannot be the same as the current scene.'); + } unset($sceneRule['use']); - unset($this->scene[$name]['use']); # 如果指定的use是一个方法 if (method_exists($this, 'use' . ucfirst($use))) { # 进行预验证,将需要传给闭包的值按指定规则进行验证 diff --git a/tests/Material/TestBaseValidate.php b/tests/Material/BaseTestValidate.php similarity index 95% rename from tests/Material/TestBaseValidate.php rename to tests/Material/BaseTestValidate.php index 6daaf47..abef497 100644 --- a/tests/Material/TestBaseValidate.php +++ b/tests/Material/BaseTestValidate.php @@ -18,7 +18,7 @@ use Illuminate\Translation\Translator; use PHPUnit\Framework\TestCase; use W7\Validate\Support\Storage\ValidateConfig; -class TestBaseValidate extends TestCase +class BaseTestValidate extends TestCase { public function __construct($name = null, array $data = [], $dataName = '') { diff --git a/tests/Material/Event/Increasing.php b/tests/Material/Event/Increasing.php new file mode 100644 index 0000000..3f9932e --- /dev/null +++ b/tests/Material/Event/Increasing.php @@ -0,0 +1,32 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material\Event; + +use Closure; +use W7\Validate\Support\Event\ValidateEventAbstract; + +class Increasing extends ValidateEventAbstract +{ + protected string $field; + + public function __construct(string $field) + { + $this->field = $field; + } + + public function afterValidate(array $data, Closure $next) + { + $data[$this->field] ++; + return $next($data); + } +} diff --git a/tests/Material/Event/SetDefault.php b/tests/Material/Event/SetDefault.php new file mode 100644 index 0000000..4ebe9aa --- /dev/null +++ b/tests/Material/Event/SetDefault.php @@ -0,0 +1,32 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material\Event; + +use Closure; +use W7\Validate\Support\Event\ValidateEventAbstract; + +class SetDefault extends ValidateEventAbstract +{ + protected array $default; + + public function __construct(array $default) + { + $this->default = $default; + } + + public function beforeValidate(array $data, Closure $next) + { + $data = array_merge($this->default, $data); + return $next($data); + } +} diff --git a/tests/Material/HandlerEventValidate.php b/tests/Material/HandlerEventValidate.php new file mode 100644 index 0000000..0ef2c6e --- /dev/null +++ b/tests/Material/HandlerEventValidate.php @@ -0,0 +1,43 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material; + +use W7\Tests\Material\Event\Increasing; +use W7\Tests\Material\Event\SetDefault; +use W7\Validate\Validate; + +class HandlerEventValidate extends Validate +{ + protected array $rule = [ + 'a' => 'required', + 'b' => 'required', + 'i' => 'required|numeric' + ]; + + protected array $scene = [ + 'setDefault' => ['a', 'b', 'handler' => [ + SetDefault::class => [[ + 'a' => 1, + 'b' => 2 + ]] + ]], + + 'incr' => ['i', 'handler' => [ + Increasing::class => 'i' + ]], + + 'useIncr' => [ + 'use' => 'incr' + ] + ]; +} diff --git a/tests/Test/TestHandlerEvent.php b/tests/Test/TestHandlerEvent.php new file mode 100644 index 0000000..e78a915 --- /dev/null +++ b/tests/Test/TestHandlerEvent.php @@ -0,0 +1,70 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\HandlerEventValidate; +use W7\Validate\Exception\ValidateException; + +class TestHandlerEvent extends BaseTestValidate +{ + /** + * @test 测试使用事件设置默认值 + * @throws ValidateException + */ + public function testEventSetDefault() + { + $v = new HandlerEventValidate(); + + $data = $v->scene('setDefault')->check([ + 'a' => 567 + ]); + + $this->assertEquals(567, $data['a']); + $this->assertEquals(2, $data['b']); + } + + /** + * @test 测试使用事件来使指定的字段递增 + * @throws ValidateException + */ + public function testIncreasing() + { + $v = new HandlerEventValidate(); + + $data = $v->scene('incr')->check([ + 'i' => 1 + ]); + + $this->assertEquals(2, $data['i']); + } + + /** + * @test 测试当验证场景中使用了use,被use的场景中的事件是否生效 + * @throws ValidateException + */ + public function testUseSceneForIncreasing() + { + $v = new HandlerEventValidate(); + + $data = $v->scene('useIncr')->check([ + 'i' => 1 + ]); + + $this->assertEquals(2, $data['i']); + + $data = $v->scene('useIncr')->check($data); + + $this->assertEquals(3, $data['i']); + } +} diff --git a/tests/Test/TestHandlerFunction.php b/tests/Test/TestHandlerFunction.php index f76d79c..fe90b89 100644 --- a/tests/Test/TestHandlerFunction.php +++ b/tests/Test/TestHandlerFunction.php @@ -13,9 +13,9 @@ namespace W7\Tests\Test; use W7\Tests\Material\HandlerDataValidate; -use W7\Tests\Material\TestBaseValidate; +use W7\Tests\Material\BaseTestValidate; -class TestHandlerFunction extends TestBaseValidate +class TestHandlerFunction extends BaseTestValidate { /** * @test 测试在after中进行最后的验证 diff --git a/tests/Test/TestValidateCollection.php b/tests/Test/TestValidateCollection.php index e581056..df8d2de 100644 --- a/tests/Test/TestValidateCollection.php +++ b/tests/Test/TestValidateCollection.php @@ -12,9 +12,9 @@ namespace W7\Tests\Test; -use W7\Tests\Material\TestBaseValidate; +use W7\Tests\Material\BaseTestValidate; -class TestValidateCollection extends TestBaseValidate +class TestValidateCollection extends BaseTestValidate { public function testGetMultiDimensionalArrays() { diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index fb83b28..b45ad6d 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -13,10 +13,10 @@ namespace W7\Tests\Test; use W7\Tests\Material\ArticleValidate; -use W7\Tests\Material\TestBaseValidate; +use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; -class TestValidateScene extends TestBaseValidate +class TestValidateScene extends BaseTestValidate { protected array $userInput; -- Gitee From 72cc7656de3a91cf0f5619a1692d34a6a90123a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 28 Apr 2021 18:00:55 +0800 Subject: [PATCH 063/152] =?UTF-8?q?[A]=20=E5=9C=A8=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E4=B8=AD=E8=BF=94=E5=9B=9E=E9=94=99=E8=AF=AF=E6=B6=88=E6=81=AF?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94=A8=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=99=A8=E4=B8=AD=E5=AE=9A=E4=B9=89=E7=9A=84=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E6=B6=88=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Validate.php b/src/Validate.php index 58402c1..8765c56 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -284,6 +284,9 @@ class Validate $data = $pipeline($data); if (is_string($data)) { + if (isset($this->message[$data])) { + $data = $this->replacingFieldsInMessage($this->message[$data]); + } throw new ValidateException($data, 403); } elseif (is_array($data)) { return $data; @@ -306,6 +309,9 @@ class Validate } $result = (new ValidateHandler($data, $this->handlers, $this->currentScene))->handle($method); if (is_string($result)) { + if (isset($this->message[$result])) { + $result = $this->replacingFieldsInMessage($this->message[$result]); + } throw new ValidateException($result, 403); } elseif (is_array($result)) { return $result; -- Gitee From af190cb6d242831acf4a80ac61024596de0fa951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 28 Apr 2021 18:04:50 +0800 Subject: [PATCH 064/152] =?UTF-8?q?[U]=20=E4=BC=98=E5=8C=96=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E7=BB=93=E6=9E=9C=E5=A4=84=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 8765c56..858b39a 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -283,16 +283,7 @@ class Validate $data = $pipeline($data); - if (is_string($data)) { - if (isset($this->message[$data])) { - $data = $this->replacingFieldsInMessage($this->message[$data]); - } - throw new ValidateException($data, 403); - } elseif (is_array($data)) { - return $data; - } - - throw new LogicException('Validate event return type error'); + return $this->handleEventResult($data); } /** @@ -308,6 +299,17 @@ class Validate return $data; } $result = (new ValidateHandler($data, $this->handlers, $this->currentScene))->handle($method); + return $this->handleEventResult($result); + } + + /** + * 处理事件结果 + * @param $result + * @return array + * @throws ValidateException + */ + private function handleEventResult($result): array + { if (is_string($result)) { if (isset($this->message[$result])) { $result = $this->replacingFieldsInMessage($this->message[$result]); -- Gitee From 5c198a7ca76147b23dafc3ace27b73c255d824cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 7 May 2021 13:45:39 +0800 Subject: [PATCH 065/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9getData?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E4=BD=BF=E5=85=B6=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E8=8E=B7=E5=8F=96=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Validate.php b/src/Validate.php index 858b39a..ce5fc5b 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -186,10 +186,15 @@ class Validate /** * 获取当前的验证数据 + * @param string $key + * @param null $default * @return array */ - public function getData(): array + public function getData(string $key = '', $default = null): array { + if (!empty($key)) { + return Arr::get($this->checkData, $key, $default); + } return $this->checkData; } -- Gitee From 33c216704d8a2aae88c71b11c00c8799351b473e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 7 May 2021 13:55:08 +0800 Subject: [PATCH 066/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DgetData?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E8=BF=94=E5=9B=9E=E7=B1=BB=E5=9E=8B=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index ce5fc5b..058c88b 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -188,9 +188,9 @@ class Validate * 获取当前的验证数据 * @param string $key * @param null $default - * @return array + * @return array|mixed */ - public function getData(string $key = '', $default = null): array + public function getData(string $key = '', $default = null) { if (!empty($key)) { return Arr::get($this->checkData, $key, $default); -- Gitee From ccda7800760dceab77ee0300867b1ed8db89a37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 8 May 2021 10:02:07 +0800 Subject: [PATCH 067/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c70ff1f..3dc6e6a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ## 安装 使用composer命令 ``` shell -composer require w7/rangine-validate +composer require w7/engine-validate ``` 完整文档查看[完整文档](https://v.neww7.com) \ No newline at end of file -- Gitee From ac190a59742a967d8d95f2dcdb99caaa1185a818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 8 May 2021 10:19:52 +0800 Subject: [PATCH 068/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=9D=99?= =?UTF-8?q?=E6=80=81make=E6=96=B9=E6=B3=95=20[A]=20=E5=A2=9E=E5=8A=A0setCu?= =?UTF-8?q?stomAttributes=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/Validate.php b/src/Validate.php index 058c88b..4f72195 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -123,6 +123,18 @@ class Validate */ private array $checkData = []; + /** + * 创建一个验证器 + * @param array $rules 验证规则 + * @param array $messages 错误消息 + * @param array $customAttributes 字段名称 + * @return Validate + */ + public static function make(array $rules, array $messages = [], array $customAttributes = []): Validate + { + return (new static())->setRules($rules)->setMessages($messages)->setCustomAttributes($customAttributes); + } + /** * 获取验证器工厂 * @return Factory @@ -1050,6 +1062,23 @@ class Validate return $this; } + /** + * 设置字段名称(叠加) + * + * @param array|null $customAttributes [字段 => 名称] 如果$customAttributes为null,则清空全部字段名称 + * @return $this + */ + public function setCustomAttributes(?array $customAttributes = null): Validate + { + if (is_null($customAttributes)) { + $this->customAttributes = []; + } else { + $this->customAttributes = array_merge($this->customAttributes, $customAttributes); + } + + return $this; + } + /** * 设置验证场景数据(叠加) * -- Gitee From e7138a247bf6b2cdddb17a9bf3268f1e5be3e21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 8 May 2021 14:20:41 +0800 Subject: [PATCH 069/152] =?UTF-8?q?[U]=20=E9=9D=99=E6=80=81=E6=96=B9?= =?UTF-8?q?=E6=B3=95make=E6=94=AF=E6=8C=81=E4=B8=8D=E4=BC=A0=E5=80=BC?= =?UTF-8?q?=E5=AE=9E=E4=BE=8B=E5=8C=96=E9=AA=8C=E8=AF=81=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Validate.php b/src/Validate.php index 4f72195..09ce88d 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -130,8 +130,11 @@ class Validate * @param array $customAttributes 字段名称 * @return Validate */ - public static function make(array $rules, array $messages = [], array $customAttributes = []): Validate + public static function make(array $rules = [], array $messages = [], array $customAttributes = []): Validate { + if (empty($rules)) { + return new static(); + } return (new static())->setRules($rules)->setMessages($messages)->setCustomAttributes($customAttributes); } -- Gitee From f8044889189dde86054c76af06418c45a936f9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 10 May 2021 10:46:43 +0800 Subject: [PATCH 070/152] =?UTF-8?q?[U]=20=E5=B0=86=E6=9C=80=E4=BD=8EPHP?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC=E9=99=8D=E4=B8=BA7.2.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- src/Exception/ValidateException.php | 2 +- src/Support/Event/ValidateEventAbstract.php | 2 +- src/Support/Rule/BaseRule.php | 4 +-- src/Support/Storage/ValidateCollection.php | 5 ++- src/Support/Storage/ValidateConfig.php | 18 +++++------ src/Support/Storage/ValidateHandler.php | 14 +++++--- src/Validate.php | 36 +++++++++++---------- tests/Material/ArticleValidate.php | 6 ++-- tests/Material/Event/Increasing.php | 2 +- tests/Material/Event/SetDefault.php | 2 +- tests/Material/HandlerDataValidate.php | 6 ++-- tests/Material/HandlerEventValidate.php | 4 +-- tests/Material/Rules/AlphaNum.php | 2 +- tests/Material/Rules/Chs.php | 2 +- tests/Material/Rules/ChsAlphaNum.php | 2 +- 16 files changed, 59 insertions(+), 50 deletions(-) diff --git a/composer.json b/composer.json index f80457c..c2c58ac 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "validate" ], "require": { - "php": "^7.4|^8.0", + "php": "^7.2.5|^8.0", "illuminate/validation": "^6.0|^7.0|^8.0" }, "require-dev": { diff --git a/src/Exception/ValidateException.php b/src/Exception/ValidateException.php index 2717785..8630015 100644 --- a/src/Exception/ValidateException.php +++ b/src/Exception/ValidateException.php @@ -17,7 +17,7 @@ use Throwable; class ValidateException extends Exception { - protected array $data = []; + protected $data = []; public function __construct($message = '', $code = 0, array $data = [], Throwable $previous = null) { diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index 1ac0131..6ca2693 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -20,7 +20,7 @@ abstract class ValidateEventAbstract implements ValidateEventInterface * 当前验证场景 * @var ?string */ - protected ?string $sceneName; + protected $sceneName; /** * 场景验证前 diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index b5abbbd..7005034 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -18,13 +18,13 @@ abstract class BaseRule implements RuleInterface * 错误消息,支持format字符串 * @var string */ - protected string $message = ''; + protected $message = ''; /** * 用于format错误消息的参数 * @var array */ - protected array $messageParam = []; + protected $messageParam = []; public function setMessage(string $message): BaseRule { diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index cabd6fc..7dea08c 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -22,7 +22,10 @@ use W7\Validate\Exception\CollectionException; class ValidateCollection extends Collection { - private ?string $paramType; + /** + * @var string|null + */ + private $paramType; /** * 将下一次取出的值强制转为int类型 diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 4efb9fb..57eb5ec 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -27,52 +27,52 @@ final class ValidateConfig * 自定义规则命名空间前缀 * @var array */ - protected array $rulesPath = []; + protected $rulesPath = []; /** * 自动加载验证器规则 * @var array */ - protected array $autoValidatePath = []; + protected $autoValidatePath = []; /** * 翻译器 * @var Translator */ - protected Translator $translator; + protected $translator; /** * 容器 * @var Container */ - protected Container $container; + protected $container; /** * 验证器工厂 * @var Factory */ - protected Factory $factory; + protected $factory; /** * 存在验证器 * @var PresenceVerifierInterface */ - protected PresenceVerifierInterface $verifier; + protected $verifier; /** * 框架类型 * 1 Laravel 2 Rangine * @var int */ - protected int $framework = 0; + protected $framework = 0; /** * 验证器具体关联 * @var array */ - protected array $validateLink = []; + protected $validateLink = []; - protected static ValidateConfig $instance; + protected static $instance; public static function instance(): ValidateConfig { diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php index a38116f..eb8850e 100644 --- a/src/Support/Storage/ValidateHandler.php +++ b/src/Support/Storage/ValidateHandler.php @@ -18,11 +18,13 @@ use W7\Validate\Support\Event\ValidateEventAbstract; class ValidateHandler { - protected array $handlers = []; + protected $handlers = []; - protected array $data = []; - - protected ?string $sceneName = null; + protected $data = []; + /** + * @var string|null + */ + protected $sceneName = null; public function __construct(array $data, array $handlers, string $sceneName = null) { @@ -62,7 +64,9 @@ class ValidateHandler $pipeline = array_reduce( array_reverse($this->pipes($method)), $this->carry(), - fn ($data) => $data + function ($data) { + return $data; + } ); return $pipeline($this->data); diff --git a/src/Validate.php b/src/Validate.php index 09ce88d..2381e59 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -31,97 +31,97 @@ class Validate * 自定义错误消息 * @var array */ - protected array $message = []; + protected $message = []; /** * 验证规则 * @var array */ - protected array $rule = []; + protected $rule = []; /** * 验证场景数据,key为控制器内的方法 * @var array */ - protected array $scene = []; + protected $scene = []; /** * 全局事件处理器 * @var array */ - protected array $handler = []; + protected $handler = []; /** * 字段名称 * @var array */ - protected array $customAttributes = []; + protected $customAttributes = []; /** * 是否首次验证失败后停止运行 * @var bool */ - protected bool $bail = true; + protected $bail = true; /** * 所有验证的字段在存在时不能为空 * @var bool */ - protected bool $filled = true; + protected $filled = true; /** * 事件优先 * @var bool */ - private bool $eventPriority = true; + private $eventPriority = true; /** * 当前验证场景 * @var ?string */ - private ?string $currentScene = null; + private $currentScene = null; /** * 验证的规则 * @var Collection */ - private Collection $checkRule; + private $checkRule; /** * 扩展方法名 * @var array */ - private static array $extendName = []; + private static $extendName = []; /** * 隐形扩展方法名 * @var array */ - private static array $implicitRules = []; + private static $implicitRules = []; /** * 验证器事件处理类 * @var array */ - private array $handlers = []; + private $handlers = []; /** * 验证前需要执行的方法 * @var array */ - private array $befores = []; + private $befores = []; /** * 验证后需要执行的方法 * @var array */ - private array $afters = []; + private $afters = []; /** * 当前进行验证的数据 * @var array */ - private array $checkData = []; + private $checkData = []; /** * 创建一个验证器 @@ -298,7 +298,9 @@ class Validate return $pipe($data, $stack); }; }, - fn ($data) => $data + function ($data) { + return $data; + } ); $data = $pipeline($data); diff --git a/tests/Material/ArticleValidate.php b/tests/Material/ArticleValidate.php index edfccf9..c9e6f10 100644 --- a/tests/Material/ArticleValidate.php +++ b/tests/Material/ArticleValidate.php @@ -16,14 +16,14 @@ use W7\Validate\Validate; class ArticleValidate extends Validate { - protected array $rule = [ + protected $rule = [ 'id' => 'required|numeric', 'content' => 'required|between:1,2000', 'title' => 'required|between:4,50|alpha|checkTitle', 'type' => 'required|numeric', ]; - protected array $message = [ + protected $message = [ 'id.required' => '缺少参数:文章Id', 'id.numeric' => '参数错误:文章Id', 'content.required' => '文章内容必须填写', @@ -36,7 +36,7 @@ class ArticleValidate extends Validate 'title.checkTitle' => '有错误啦' ]; - protected array $scene = [ + protected $scene = [ 'add' => ['content', 'title'], 'save' => ['use' => 'edit'], 'del' => ['id'], diff --git a/tests/Material/Event/Increasing.php b/tests/Material/Event/Increasing.php index 3f9932e..c7c645f 100644 --- a/tests/Material/Event/Increasing.php +++ b/tests/Material/Event/Increasing.php @@ -17,7 +17,7 @@ use W7\Validate\Support\Event\ValidateEventAbstract; class Increasing extends ValidateEventAbstract { - protected string $field; + protected $field; public function __construct(string $field) { diff --git a/tests/Material/Event/SetDefault.php b/tests/Material/Event/SetDefault.php index 4ebe9aa..3eaa796 100644 --- a/tests/Material/Event/SetDefault.php +++ b/tests/Material/Event/SetDefault.php @@ -17,7 +17,7 @@ use W7\Validate\Support\Event\ValidateEventAbstract; class SetDefault extends ValidateEventAbstract { - protected array $default; + protected $default; public function __construct(array $default) { diff --git a/tests/Material/HandlerDataValidate.php b/tests/Material/HandlerDataValidate.php index f70e024..3405789 100644 --- a/tests/Material/HandlerDataValidate.php +++ b/tests/Material/HandlerDataValidate.php @@ -16,17 +16,17 @@ use W7\Validate\Validate; class HandlerDataValidate extends Validate { - protected array $rule = [ + protected $rule = [ 'user' => 'required|array', 'user.*' => 'chsAlphaNum', 'name' => 'required|Chs' ]; - protected array $customAttributes = [ + protected $customAttributes = [ 'name' => '名称' ]; - protected array $scene = [ + protected $scene = [ 'afterRule' => ['user', 'user.*', 'after' => 'checkUserNotRepeat'], 'addData' => ['user', 'user.*', 'after' => 'addData'], 'beforeHandlerData' => ['name', 'before' => 'setDefaultName'], diff --git a/tests/Material/HandlerEventValidate.php b/tests/Material/HandlerEventValidate.php index 0ef2c6e..09de3f6 100644 --- a/tests/Material/HandlerEventValidate.php +++ b/tests/Material/HandlerEventValidate.php @@ -18,13 +18,13 @@ use W7\Validate\Validate; class HandlerEventValidate extends Validate { - protected array $rule = [ + protected $rule = [ 'a' => 'required', 'b' => 'required', 'i' => 'required|numeric' ]; - protected array $scene = [ + protected $scene = [ 'setDefault' => ['a', 'b', 'handler' => [ SetDefault::class => [[ 'a' => 1, diff --git a/tests/Material/Rules/AlphaNum.php b/tests/Material/Rules/AlphaNum.php index f459f20..dbaf896 100644 --- a/tests/Material/Rules/AlphaNum.php +++ b/tests/Material/Rules/AlphaNum.php @@ -16,7 +16,7 @@ use W7\Validate\Support\Rule\BaseRule; class AlphaNum extends BaseRule { - protected string $message = ':attribute的值只能具有英文字母,数字'; + protected $message = ':attribute的值只能具有英文字母,数字'; public function passes($attribute, $value): bool { diff --git a/tests/Material/Rules/Chs.php b/tests/Material/Rules/Chs.php index e0425b9..636d868 100644 --- a/tests/Material/Rules/Chs.php +++ b/tests/Material/Rules/Chs.php @@ -20,7 +20,7 @@ class Chs extends BaseRule * 默认错误消息 * @var string */ - protected string $message = ':attribute的值只能具有中文'; + protected $message = ':attribute的值只能具有中文'; /** * 确定验证规则是否通过。 diff --git a/tests/Material/Rules/ChsAlphaNum.php b/tests/Material/Rules/ChsAlphaNum.php index 365aee0..72c47ff 100644 --- a/tests/Material/Rules/ChsAlphaNum.php +++ b/tests/Material/Rules/ChsAlphaNum.php @@ -16,7 +16,7 @@ use W7\Validate\Support\Rule\BaseRule; class ChsAlphaNum extends BaseRule { - protected string $message = ':attribute的值只能具有中文,字母,数字'; + protected $message = ':attribute的值只能具有中文,字母,数字'; public function passes($attribute, $value): bool { -- Gitee From c0219e2c366bfa553e57f7dcb54b8597c9c60c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 10 May 2021 11:05:50 +0800 Subject: [PATCH 071/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E9=A1=B9=EF=BC=8C=E4=BB=A5=E9=80=82=E9=85=8DPHP7.2.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 7 ++++--- tests/Material/BaseTestValidate.php | 7 ++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index c2c58ac..d6b4189 100644 --- a/composer.json +++ b/composer.json @@ -17,11 +17,12 @@ ], "require": { "php": "^7.2.5|^8.0", - "illuminate/validation": "^6.0|^7.0|^8.0" + "illuminate/validation": "^6.0|^7.0" }, "require-dev": { - "phpunit/phpunit" : "^9.5", - "friendsofphp/php-cs-fixer": "^2.18" + "friendsofphp/php-cs-fixer": "^2.18", + "laravel-lang/lang": "^8.0", + "phpunit/phpunit": "^8.5" }, "autoload": { "psr-4": { diff --git a/tests/Material/BaseTestValidate.php b/tests/Material/BaseTestValidate.php index abef497..af2dae4 100644 --- a/tests/Material/BaseTestValidate.php +++ b/tests/Material/BaseTestValidate.php @@ -22,7 +22,12 @@ class BaseTestValidate extends TestCase { public function __construct($name = null, array $data = [], $dataName = '') { - $loader = new FileLoader(new Filesystem(), dirname(__DIR__, 2)); + $langPath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'laravel-lang' . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR; + if (!file_exists($langPath . 'locales')) { + $langPath .= 'src'; + } + + $loader = new FileLoader(new Filesystem(), $langPath); $translator = new Translator($loader, 'zh_CN'); ValidateConfig::instance()->setTranslator($translator); -- Gitee From bde425bdd4f1a8124b7ed73543c36adcaf4832df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 13 May 2021 16:07:25 +0800 Subject: [PATCH 072/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E8=A7=84?= =?UTF-8?q?=E5=88=99=E7=AE=A1=E7=90=86=E5=99=A8=20[A]=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E7=B1=BB=20[A]=20=E5=A2=9E=E5=8A=A0=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=A4=84=E7=90=86=E5=99=A8=20[U]=20=E5=AF=B9=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=BF=9B=E8=A1=8C=E4=BA=86=E5=A4=A7=E9=87=8F=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20[F]=20=E4=BF=AE=E5=A4=8D=E8=87=AA=E5=8A=A8=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E7=BF=BB=E8=AF=91=E5=99=A8=E5=9B=A0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=AF=BC=E8=87=B4=E6=89=BE=E4=B8=8D=E5=88=B0?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E5=8C=85=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + src/RuleManager.php | 508 ++++++++++ src/Support/Common.php | 57 ++ .../Concerns/MessageProviderInterface.php | 76 ++ src/Support/Concerns/SceneInterface.php | 65 ++ src/Support/MessageProvider.php | 123 +++ src/Support/RuleManagerScene.php | 123 +++ src/Support/Storage/ValidateConfig.php | 14 +- src/Support/ValidateScene.php | 198 ++++ src/Support/helpers.php | 9 +- src/Validate.php | 948 +++--------------- tests/Material/ArticleValidate.php | 9 +- tests/Material/BaseTestValidate.php | 4 +- tests/Material/HandlerDataValidate.php | 9 +- tests/Material/Rules/Length.php | 37 + tests/Material/Rules/LengthBetween.php | 40 + tests/Test/TestValidateMessage.php | 65 ++ tests/Test/TestValidateScene.php | 111 +- 18 files changed, 1582 insertions(+), 815 deletions(-) create mode 100644 src/RuleManager.php create mode 100644 src/Support/Common.php create mode 100644 src/Support/Concerns/MessageProviderInterface.php create mode 100644 src/Support/Concerns/SceneInterface.php create mode 100644 src/Support/MessageProvider.php create mode 100644 src/Support/RuleManagerScene.php create mode 100644 src/Support/ValidateScene.php create mode 100644 tests/Material/Rules/Length.php create mode 100644 tests/Material/Rules/LengthBetween.php create mode 100644 tests/Test/TestValidateMessage.php diff --git a/README.md b/README.md index 3dc6e6a..d552854 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # 软擎验证扩展 +为具体的验证场景或者数据表定义好验证器类,调用验证类的check方法即可完成验证,然后你将得到一个安全可用的数据。 ## 说明 此验证基于Laravel的Validator验证器,可用于Laravel,软擎等依赖于illuminate/validation的项目中,此验证器做了如下扩展: diff --git a/src/RuleManager.php b/src/RuleManager.php new file mode 100644 index 0000000..c5f3c18 --- /dev/null +++ b/src/RuleManager.php @@ -0,0 +1,508 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate; + +use Closure; +use Illuminate\Contracts\Validation\ImplicitRule; +use W7\Validate\Support\Common; +use W7\Validate\Support\Rule\BaseRule; +use W7\Validate\Support\RuleManagerScene; +use W7\Validate\Support\Storage\ValidateConfig; + +class RuleManager +{ + /** + * All original validation rules + * @var array + */ + protected $rule = []; + + /** + * Define a scenario for the validation rule + * @var array + */ + protected $scene = []; + + /** + * The array of custom attribute names. + * + * @var array + */ + protected $customAttributes = []; + + /** + * The array of custom error messages. + * + * @var array + */ + protected $message = []; + + /** + * Current validate scene + * @var string|null + */ + private $currentScene = null; + + /** + * Extension method name + * @var array + */ + private static $extendName = []; + + /** + * Implicit extension method name + * @var array + */ + private static $implicitRules = []; + + /** + * Set current validate scene + * + * @param string|null $name + * @return $this + */ + public function scene(?string $name): RuleManager + { + $this->currentScene = $name; + return $this; + } + + /** + * Get the name of the current validate scene + * + * @return string|null + */ + public function getCurrentSceneName(): ?string + { + return $this->currentScene; + } + + /** + * Get initial rules provided + * + * @param string|null $sceneName The scene name, or the current scene name if not provided. + * @return array + */ + public function getRules(?string $sceneName = ''): array + { + if ('' === $sceneName) { + $sceneName = $this->currentScene; + } + + if (empty($sceneName)) { + return $this->rule; + } + + if (method_exists($this, 'scene' . ucfirst($sceneName))) { + $scene = new RuleManagerScene($this->rule); + call_user_func([$this, 'scene' . ucfirst($sceneName)], $scene); + return $scene->getRules(); + } + + if (isset($this->scene[$sceneName])) { + return array_intersect_key($this->rule, array_flip((array) $this->scene[$sceneName])); + } + + return $this->rule; + } + + /** + * Converting raw rules into rules for checking data + * + * @param array|null $rules If this parameter is not provided, it will be retrieved by default from the `getRules` method + * @return array|array[] + */ + public function getCheckRules(?array $rules = null): array + { + if (is_null($rules)) { + $rules = $this->getRules(); + } + $rulesFields = array_keys($rules); + $rule = array_map(function ($rules, $field) { + if (!is_array($rules)) { + $rules = explode('|', $rules); + } + + return array_map(function ($ruleName) use ($field) { + if (is_string($ruleName)) { + $ruleClass = $this->getRuleClass($ruleName); + if (false !== $ruleClass) { + if (!empty($message = $this->getMessages($field, $ruleName))) { + $ruleClass->setMessage($message); + } + return $ruleClass; + } + + return $this->getExtendsRule($ruleName, $field); + } + + return $ruleName; + }, $rules); + }, $rules, $rulesFields); + + return array_combine($rulesFields, $rule); + } + + /** + * Get the instance class of a custom rule + * + * @param string $ruleName Custom Rule Name + * @return false|BaseRule + */ + private function getRuleClass(string $ruleName) + { + list($ruleName, $param) = Common::getKeyAndParam($ruleName, true); + + foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { + $ruleNameSpace = $rulesPath . ucfirst($ruleName); + if (class_exists($ruleNameSpace) && is_subclass_of($ruleNameSpace, BaseRule::class)) { + return new $ruleNameSpace(...$param); + } + } + + return false; + } + + /** + * Register a custom validator extension. + * + * @param string $rule Rule Name + * @param Closure|string|array $extension Closure rules, providing four parameters:$attribute, $value, $parameters, $validator + * @param string|null $message Error Message + */ + public static function extend(string $rule, $extension, ?string $message = null) + { + self::validatorExtend('', $rule, $extension, $message); + } + + /** + * Register a custom implicit validator extension. + * + * @param string $rule Rule Name + * @param Closure|string|array $extension Closure rules, providing four parameters:$attribute, $value, $parameters, $validator + * @param string|null $message Error Message + */ + public static function extendImplicit(string $rule, $extension, ?string $message = null) + { + self::validatorExtend('Implicit', $rule, $extension, $message); + } + + /** + * Register a custom dependent validator extension. + * + * @param string $rule Rule Name + * @param Closure|string|array $extension Closure rules, providing four parameters:$attribute, $value, $parameters, $validator + * @param string|null $message Error Message + */ + public static function extendDependent(string $rule, $extension, ?string $message = null) + { + self::validatorExtend('Dependent', $rule, $extension, $message); + } + + /** + * Register a custom validator message replacer. + * + * @param string $rule Rule Name + * @param string|Closure $replacer Closure rules, providing four parameters:$message,$attribute,$rule,$parameters + */ + public static function replacer(string $rule, $replacer) + { + if (array_key_exists($rule, self::$extendName)) { + $ruleName = md5(get_called_class() . $rule); + if (in_array($ruleName, self::$extendName[$rule])) { + $rule = $ruleName; + } + } + ValidateConfig::instance()->getFactory()->replacer($rule, $replacer); + } + + /** + * Register for custom validator extensions + * + * @param string $type Type + * @param string $rule Rule Name + * @param Closure|string|array $extension Closure rules, providing four parameters:$attribute, $value, $parameters, $validator + * @param string|null $message Error Messages + */ + private static function validatorExtend(string $type, string $rule, $extension, ?string $message = null) + { + // Multiple rule managers using the same rule will result in the later methods not taking effect. + // So here a unique rule name is generated based on the namespace. + $ruleName = md5(get_called_class() . $rule); + + if (array_key_exists($rule, self::$extendName)) { + array_push(self::$extendName[$rule], $ruleName); + self::$extendName[$rule] = array_unique(self::$extendName[$rule]); + } else { + self::$extendName[$rule] = [$ruleName]; + } + + if (!empty($type)) { + $method = 'extend' . $type; + } else { + $method = 'extend'; + } + + if ('Implicit' === $type) { + self::$implicitRules[] = $ruleName; + } + + ValidateConfig::instance()->getFactory()->$method($ruleName, $extension, $message); + } + + /** + * Get extension rules + * + * The method names are processed due to the need to distinguish the same custom method names for multiple validators. + * This method is used in order to make the rules correspond to the processed method names. + * @param string $ruleName + * @param string|null $field + * @return string + */ + private function getExtendsRule(string $ruleName, string $field = null): string + { + list($rule, $param) = Common::getKeyAndParam($ruleName, false); + + # Retrieve the real custom rule method name, and modify the corresponding error message + if (array_key_exists($rule, self::$extendName)) { + $ruleName = md5(get_called_class() . $rule); + # Determine if an error message is defined for a custom rule method + if (null !== $field && isset($this->message[$field . '.' . $rule])) { + $this->message[$ruleName] = $this->message[$field . '.' . $rule]; + } + + $rule = $ruleName; + } else { + # If it does not exist in the current custom rule, determine if it is a class method + # If it is a class method, register the rule to the rule manager first, + # and then process the corresponding error message + if (method_exists($this, 'rule' . ucfirst($rule))) { + self::extend($rule, Closure::fromCallable([$this, 'rule' . ucfirst($rule)])); + + if ('' !== $param) { + $rule = $rule . ':' . $param; + } + + return $this->getExtendsRule($rule, $field); + } + } + + if ('' !== $param) { + $rule = $rule . ':' . $param; + } + return $rule; + } + + /** + * Add the `bail` rule + * + * @param array $rules Original Rules + * @return array + */ + protected function addBailRule(array $rules): array + { + foreach ($rules as &$rule) { + if (!in_array('bail', $rule)) { + array_unshift($rule, 'bail'); + } + } + + return $rules; + } + + /** + * Add the `filled` rule + * + * @param array $rules Original Rules + * @return array + */ + protected function addFilledRule(array $rules): array + { + $conflictRules = [ + 'filled', 'nullable', 'accepted', 'present', 'required', 'required_if', 'required_unless', 'required_with', + 'required_with_all', 'required_without', 'required_without_all', + ]; + + foreach ($rules as &$rule) { + $rulesName = array_map(function ($value) { + if (is_object($value)) { + // By default, when an attribute being validated is not present or contains an empty string, + // normal validation rules, including custom extensions, are not run. + // If the ImplicitRule interface is implemented, + // it means that the rule object needs to be run even if the property is empty. + // So there is no need for the `filled` rule either, + // so let there be a `filled` in the array object to skip this process. + if ($value instanceof ImplicitRule) { + return 'filled'; + } else { + return ''; + } + } + + $ruleName = Common::getKeyAndParam($value)[0]; + + if (in_array($ruleName, self::$implicitRules)) { + return 'filled'; + } + + return $ruleName; + }, $rule); + + if (empty(array_intersect($conflictRules, $rulesName))) { + array_unshift($rule, 'filled'); + } + } + + return $rules; + } + + /** + * Set validator scene data (overlay) + * + * @param array|null $scene [Scene => [Field]] If $Scene is null, clear all validation scenes + * @return static + */ + public function setScene(?array $scene = null): RuleManager + { + if (is_null($scene)) { + $this->scene = []; + } else { + $this->scene = array_merge($this->scene, $scene); + } + + return $this; + } + + /** + * Set validator rules (overlay) + * + * @param array|null $rules [field => rules] If $rules is null, clear all validation rules + * @return $this + */ + public function setRules(?array $rules = null): RuleManager + { + if (is_null($rules)) { + $this->rule = []; + } else { + $this->rule = array_merge($this->rule, $rules); + } + + return $this; + } + + /** + * Set the Message(overlay) + * + * @param array|null $message [Field. Rule => validation message] If $message is null,clear all validation messages + * @return $this + */ + public function setMessages(?array $message = null): RuleManager + { + if (is_null($message)) { + $this->message = []; + } else { + $this->message = array_merge($this->message, $message); + } + + return $this; + } + + /** + * Get the defined error message + * + * + * If you want to get the error messages after validate, use the `getMessages` method of the message processor + * + *

If you have defined an extension rule using the {@see RuleManager}, + * you need to call the `getCheckRules` method first before calling this method. + * Otherwise the error message may not match the extension rule name.

+ * @param string|null $key Full message key,if $keys is null,then get all messages + * @param string|null $rule If the first value is a field name, the second value is a rule, otherwise leave it blank + * @return array|string|null + */ + public function getMessages(?string $key = null, ?string $rule = null) + { + if (null === $key) { + return $this->message; + } + + if (null !== $rule) { + $messageName = Common::makeMessageName($key, $rule); + } else { + $messageName = $key; + } + + return $this->message[$messageName] ?? ''; + } + + /** + * Set the custom attributes(overlay) + * + * @param array|null $customAttributes [fields => names] If $customAttributes is null, clear all field names + * @return $this + */ + public function setCustomAttributes(?array $customAttributes = null): RuleManager + { + if (is_null($customAttributes)) { + $this->customAttributes = []; + } else { + $this->customAttributes = array_merge($this->customAttributes, $customAttributes); + } + + return $this; + } + + /** + * Get array of custom attribute names. + * @return array + */ + public function getCustomAttributes(): array + { + return $this->customAttributes; + } + + public static function get($fields = null, $initial = true): array + { + $validate = new static(); + if (null === $fields) { + $rules = $validate->getRules(null); + if (!$initial) { + $rules = $validate->getCheckRules($rules); + } + $message = $validate->getMessages(); + $customAttributes = $validate->getCustomAttributes(); + } else { + if (!is_array($fields)) { + $fields = [$fields]; + } + + $rules = array_intersect_key($validate->getRules(null), array_flip($fields)); + if (!$initial) { + $rules = $validate->getCheckRules($rules); + } + + $message = array_filter($validate->getMessages(), function ($value, $key) use ($fields) { + foreach ($fields as $field) { + if (0 === strrpos($key, $field)) { + return true; + } + } + return false; + }, ARRAY_FILTER_USE_BOTH); + + $customAttributes = array_intersect_key($validate->getCustomAttributes(), array_flip($fields)); + } + + return [$rules, $message, $customAttributes]; + } +} diff --git a/src/Support/Common.php b/src/Support/Common.php new file mode 100644 index 0000000..18f1711 --- /dev/null +++ b/src/Support/Common.php @@ -0,0 +1,57 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support; + +class Common +{ + /** + * Get the name and parameters of the rule + * + * @param string $value Complete Rules + * @param bool $parsing Whether to parse parameters, default is false + * @return array + */ + public static function getKeyAndParam(string $value, bool $parsing = false): array + { + $param = ''; + if (false !== strpos($value, ':')) { + $arg = explode(':', $value, 2); + $key = $arg[0]; + if (count($arg) >= 2) { + $param = $arg[1]; + } + } else { + $key = $value; + } + + if ($parsing) { + $param = explode(',', $param); + } + return [$key, $param]; + } + + /** + * Name of the generated error message + * + * @param string $fieldName + * @param string $rule + * @return string + */ + public static function makeMessageName(string $fieldName, string $rule): string + { + if (false !== strpos($rule, ':')) { + $rule = substr($rule, 0, strpos($rule, ':')); + } + return $fieldName . '.' . $rule; + } +} diff --git a/src/Support/Concerns/MessageProviderInterface.php b/src/Support/Concerns/MessageProviderInterface.php new file mode 100644 index 0000000..62084d4 --- /dev/null +++ b/src/Support/Concerns/MessageProviderInterface.php @@ -0,0 +1,76 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Concerns; + +use W7\Validate\RuleManager; + +interface MessageProviderInterface +{ + /** + * Handling a message + * + * @param string|string[]$messages + * @return string|string[] + */ + public function handleMessage($messages); + + /** + * Get a validation message for the processed attributes and rules. + * + * @param string $key + * @param string|null $rule + * @return string + */ + public function getMessage(string $key, ?string $rule = null): ?string; + + /** + * Get the Initial validation message for an attribute and rule. + * + * @param string $key + * @param string|null $rule + * @return string + */ + public function getInitialMessage(string $key, ?string $rule = null): ?string; + + /** + * Provide array of error messages. + * + * @param array $messages + * @return mixed + */ + public function setMessage(array $messages): MessageProviderInterface; + + /** + * Provide array of custom attribute names. + * + * @param array $customAttributes + * @return MessageProviderInterface + */ + public function setCustomAttributes(array $customAttributes): MessageProviderInterface; + + /** + * Provide data for validation + * + * @param array $data + * @return MessageProviderInterface + */ + public function setData(array $data): MessageProviderInterface; + + /** + * Provide RuleManager for validation + * + * @param RuleManager $ruleManager + * @return MessageProviderInterface + */ + public function setRuleManager(RuleManager $ruleManager): MessageProviderInterface; +} diff --git a/src/Support/Concerns/SceneInterface.php b/src/Support/Concerns/SceneInterface.php new file mode 100644 index 0000000..5be48eb --- /dev/null +++ b/src/Support/Concerns/SceneInterface.php @@ -0,0 +1,65 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Concerns; + +interface SceneInterface +{ + /** + * Specify the list of fields to be validated + * + * @param array $fields + * @return $this + */ + public function only(array $fields): SceneInterface; + + /** + * Adding a validation rule for a field + * + * @param string $field + * @param string|array $rules + * @return $this + */ + public function append(string $field, $rules): SceneInterface; + + /** + * Remove the validation rule for a field + * + * @param string $field + * @param array|string|null $rule Validate rules.if $rule is null,remove all rules from the current field + * @return $this + */ + public function remove(string $field, $rule = null): SceneInterface; + + /** + * Add fields to the validation list + * + * @param string $field + * @return $this + */ + public function appendCheckField(string $field): SceneInterface; + + /** + * Delete fields from the validation list + * + * @param string $field + * @return $this + */ + public function removeCheckField(string $field): SceneInterface; + + /** + * Get validate rules + * + * @return array + */ + public function getRules(): array; +} diff --git a/src/Support/MessageProvider.php b/src/Support/MessageProvider.php new file mode 100644 index 0000000..0d24762 --- /dev/null +++ b/src/Support/MessageProvider.php @@ -0,0 +1,123 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support; + +use Illuminate\Support\Arr; +use W7\Validate\RuleManager; +use W7\Validate\Support\Concerns\MessageProviderInterface; + +class MessageProvider implements MessageProviderInterface +{ + /** + * The array of custom attribute names. + * + * @var array + */ + protected $customAttributes = []; + + /** + * The array of custom error messages. + * + * @var array + */ + protected $message = []; + + /** + * Data for validate + * + * @var array + */ + protected $data = []; + + /** @inheritDoc */ + public function setRuleManager(RuleManager $ruleManager): MessageProviderInterface + { + $this->message = $ruleManager->getMessages(); + $this->customAttributes = $ruleManager->getCustomAttributes(); + return $this; + } + + /** @inheritDoc */ + public function setMessage(array $messages): MessageProviderInterface + { + $this->message = $messages; + return $this; + } + + /** @inheritDoc */ + public function setCustomAttributes(array $customAttributes): MessageProviderInterface + { + $this->customAttributes = $customAttributes; + return $this; + } + + /** @inheritDoc */ + public function setData(array $data): MessageProviderInterface + { + $this->data = $data; + return $this; + } + + /** @inheritDoc */ + public function getInitialMessage(string $key, ?string $rule = null): ?string + { + if (null !== $rule) { + $messageName = Common::makeMessageName($key, $rule); + } else { + $messageName = $key; + } + + return $this->message[$messageName] ?? ''; + } + + /** @inheritDoc */ + public function handleMessage($messages) + { + if (is_array($messages)) { + foreach ($messages as &$errorMessages) { + if (is_array($errorMessages)) { + $errorMessages = array_map([$this, 'replacingFieldsInMessage'], $errorMessages); + } else { + $errorMessages = $this->replacingFieldsInMessage($errorMessages); + } + } + + return $messages; + } + + return $this->replacingFieldsInMessage($messages); + } + + /** @inheritDoc */ + public function getMessage(string $key, ?string $rule = null): ?string + { + $error = $this->getInitialMessage($key, $rule); + return $this->replacingFieldsInMessage($error); + } + + /** + * Replacing fields in error messages + * + * @param string $message + * @return string|string[] + */ + private function replacingFieldsInMessage(string $message) + { + if (preg_match_all('/{:(.*?)}/', $message, $matches) > 0) { + foreach ($matches[0] as $index => $pregString) { + $message = str_replace($pregString, Arr::get($this->data, $matches[1][$index], ''), $message); + } + } + return $message; + } +} diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php new file mode 100644 index 0000000..f680450 --- /dev/null +++ b/src/Support/RuleManagerScene.php @@ -0,0 +1,123 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support; + +use W7\Validate\Support\Concerns\SceneInterface; + +class RuleManagerScene implements SceneInterface +{ + /** + * The rules to be applied to the data. + * @var array + */ + protected $checkRules; + + /** + * RuleManagerScene constructor. + * @param array $checkRules The rules to be applied to the data. + */ + public function __construct(array $checkRules = []) + { + $this->checkRules = $checkRules; + } + + /** @inheritDoc */ + public function only(array $fields): SceneInterface + { + $this->checkRules = array_intersect_key($this->checkRules, array_flip($fields)); + return $this; + } + + /** @inheritDoc */ + public function append(string $field, $rules): SceneInterface + { + if (isset($this->checkRules[$field])) { + if (!is_array($this->checkRules[$field])) { + $this->checkRules[$field] = explode('|', $this->checkRules[$field]); + } + + if (!is_array($rules)) { + $rules = explode('|', $rules); + } + array_push($this->checkRules[$field], ...$rules); + } + + return $this; + } + + /** @inheritDoc */ + public function remove(string $field, $rule = null): SceneInterface + { + $removeRule = $rule; + if (is_string($rule) && false !== strpos($rule, '|')) { + $removeRule = explode('|', $rule); + } + + if (is_array($removeRule)) { + foreach ($removeRule as $rule) { + $this->remove($field, $rule); + } + + return $this; + } + + if (isset($this->checkRules[$field])) { + if (null === $rule) { + $this->checkRules[$field] = []; + return $this; + } + + $rules = $this->checkRules[$field]; + + if (is_string($rules)) { + $rules = explode('|', $rules); + } + + if (false !== strpos($rule, ':')) { + $rule = substr($rule, 0, strpos($rule, ':')); + } + + $rules = array_filter($rules, function ($value) use ($rule) { + if (false !== strpos($value, ':')) { + $value = substr($value, 0, strpos($value, ':')); + } + return $value !== $rule; + }); + + $this->checkRules[$field] = $rules; + } + + return $this; + } + + /** @inheritDoc */ + public function appendCheckField(string $field): SceneInterface + { + $rule = $this->rule[$field] ?? ''; + $this->checkRules = array_merge($this->checkRules, [$field => $rule]); + return $this; + } + + /** @inheritDoc */ + public function removeCheckField(string $field): SceneInterface + { + unset($this->checkRules[$field]); + return $this; + } + + /** @inheritDoc */ + public function getRules(): array + { + return $this->checkRules; + } +} diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 57eb5ec..868daf1 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -20,6 +20,8 @@ use Illuminate\Support\Facades\App; use Illuminate\Translation\FileLoader; use Illuminate\Validation\Factory; use Illuminate\Validation\PresenceVerifierInterface; +use ReflectionClass; +use RuntimeException; final class ValidateConfig { @@ -120,7 +122,7 @@ final class ValidateConfig $this->factory = \W7\Facade\Container::singleton("W7\Contract\Validation\ValidatorFactoryInterface"); break; default: - throw new \RuntimeException('Framework Type Error'); + throw new RuntimeException('Framework Type Error'); } } else { $this->factory = new Factory($this->getTranslator(), $this->getContainer()); @@ -191,9 +193,15 @@ final class ValidateConfig private function getTranslator(): Translator { if (empty($this->translator)) { - $reflection = new \ReflectionClass(ClassLoader::class); + $reflection = new ReflectionClass(ClassLoader::class); $vendorDir = dirname($reflection->getFileName(), 2); - $loader = new FileLoader(new Filesystem(), $vendorDir); + $langPath = $vendorDir . DIRECTORY_SEPARATOR . 'laravel-lang' . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR; + if (file_exists($langPath . 'locales')) { + $langPath .= 'locales'; + } else { + $langPath .= 'src'; + } + $loader = new FileLoader(new Filesystem(), $langPath); return new \Illuminate\Translation\Translator($loader, 'zh_CN'); } diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php new file mode 100644 index 0000000..4a061c7 --- /dev/null +++ b/src/Support/ValidateScene.php @@ -0,0 +1,198 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support; + +use Illuminate\Support\Arr; +use RuntimeException; +use W7\Validate\Support\Rule\BaseRule; +use W7\Validate\Support\Storage\ValidateCollection; + +/** + * Class ValidateScene + * @package W7\Validate\Support + * + * @property-read array $handlers Events to be processed + * @property-read array $afters Methods to be executed after validation + * @property-read array $befores Methods to be executed before validation + * @property-read bool $eventPriority Event Priority + */ +class ValidateScene extends RuleManagerScene +{ + /** + * Data to be validated + * @var array + */ + protected $checkData = []; + + /** + * Events to be processed + * @var array + */ + protected $handlers = []; + + /** + * Methods to be executed after validation + * @var array + */ + protected $afters = []; + + /** + * Methods to be executed before validation + * @var array + */ + protected $befores = []; + + /** + * Event Priority + * @var bool + */ + private $eventPriority; + + /** + * ValidateScene constructor. + * @param array $checkRules + * @param array $checkData + */ + public function __construct(array $checkRules = [], array $checkData = []) + { + parent::__construct($checkRules); + $this->checkData = $checkData; + } + + public function __get($name) + { + if (property_exists($this, $name)) { + return $this->$name; + } + + throw new RuntimeException('Unknown property:' . $name); + } + + /** + * Add conditions to a given field based on a Closure. + * + * @param string|string[] $attribute field name + * @param string|array|BaseRule $rules rules + * @param callable $callback Closure,method provides a {@see ValidateCollection} $data parameter, + * which is the current validation data, + * if the Closure passed as the third argument returns true, the rules will be added. + * @return $this + */ + public function sometimes($attribute, $rules, callable $callback): ValidateScene + { + $data = $this->getValidateData(); + $result = call_user_func($callback, $data); + + if (!$result) { + return $this; + } + + if (is_array($attribute)) { + foreach ($attribute as $filed) { + $this->append($filed, $rules); + } + } else { + $this->append($attribute, $rules); + } + + return $this; + } + + /** + * Join the event + * + * @param string $handler Full class name of the event, full namespace string or add ::class + * @param mixed ...$params Parameters to be passed to the event + * @return $this + */ + public function handler(string $handler, ...$params): ValidateScene + { + $this->handlers[] = [$handler, $params]; + return $this; + } + + /** + * Add a method that needs to be executed before validation + * + * @param string $callbackName Validate the method name in the class + * @param mixed ...$params Parameters to be passed to the method + * @return $this + */ + public function before(string $callbackName, ...$params): ValidateScene + { + $this->befores[] = [$callbackName, $params]; + return $this; + } + + /** + * Add a method that needs to be executed after validation + * + * @param string $callbackName Validate the method name in the class + * @param mixed ...$params Parameters to be passed to the method + * @return $this + */ + public function after(string $callbackName, ...$params): ValidateScene + { + $this->afters[] = [$callbackName, $params]; + return $this; + } + + /** + * Set event priority + * + * @param bool $priority + * @return $this + */ + public function setEventPriority(bool $priority): ValidateScene + { + $this->eventPriority = $priority; + return $this; + } + + /** + * Provide the data to be validated + * + * @param array $data + * @return $this + */ + public function setData(array $data = []): ValidateScene + { + $this->checkData = $data; + return $this; + } + + /** + * Get the current validation data + * + * @param string $key + * @param mixed $default + * @return array|mixed + */ + public function getData(string $key = '', $default = null) + { + if (!empty($key)) { + return Arr::get($this->checkData, $key, $default); + } + return $this->checkData; + } + + /** + * Get the current validation data,Return the {@see ValidateCollection} type + * + * @return ValidateCollection + */ + public function getValidateData(): ValidateCollection + { + return validate_collect($this->getData()); + } +} diff --git a/src/Support/helpers.php b/src/Support/helpers.php index a29ece7..64fad0a 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -16,7 +16,7 @@ use W7\Validate\Support\Storage\ValidateCollection; if (!function_exists('validate_collect')) { /** - * 数值转为验证器集合ValidateCollection类型 + * Create a ValidateCollection from the given value. * @param null $value * @return ValidateCollection */ @@ -28,9 +28,10 @@ if (!function_exists('validate_collect')) { if (!function_exists('get_validate_data')) { /** - * 获取验证后的结果 - * @param ServerRequestInterface|Request $request 请求示例 - * @return ValidateCollection 返回验证器集合ValidateCollection类型 + * Get the result after verification + * + * @param ServerRequestInterface|Request $request Request Example + * @return ValidateCollection */ function get_validate_data($request = null): ValidateCollection { diff --git a/src/Validate.php b/src/Validate.php index 2381e59..e7fd5f8 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -12,122 +12,78 @@ namespace W7\Validate; -use Closure; -use Illuminate\Contracts\Validation\ImplicitRule; -use Illuminate\Support\Arr; -use Illuminate\Support\Collection; use Illuminate\Validation\Factory; use Illuminate\Validation\ValidationException; use LogicException; use W7\Validate\Exception\ValidateException; -use W7\Validate\Support\Rule\BaseRule; -use W7\Validate\Support\Storage\ValidateCollection; +use W7\Validate\Support\Concerns\MessageProviderInterface; +use W7\Validate\Support\MessageProvider; use W7\Validate\Support\Storage\ValidateConfig; use W7\Validate\Support\Storage\ValidateHandler; +use W7\Validate\Support\ValidateScene; -class Validate +class Validate extends RuleManager { /** - * 自定义错误消息 - * @var array - */ - protected $message = []; - - /** - * 验证规则 - * @var array - */ - protected $rule = []; - - /** - * 验证场景数据,key为控制器内的方法 - * @var array - */ - protected $scene = []; - - /** - * 全局事件处理器 + * Global Event Handler * @var array */ protected $handler = []; /** - * 字段名称 - * @var array - */ - protected $customAttributes = []; - - /** - * 是否首次验证失败后停止运行 + * Whether to stop running after the first verification failure * @var bool */ protected $bail = true; /** - * 所有验证的字段在存在时不能为空 + * All validated fields cannot be empty when present * @var bool */ protected $filled = true; /** - * 事件优先 + * Event Priority * @var bool */ private $eventPriority = true; /** - * 当前验证场景 - * @var ?string - */ - private $currentScene = null; - - /** - * 验证的规则 - * @var Collection - */ - private $checkRule; - - /** - * 扩展方法名 - * @var array - */ - private static $extendName = []; - - /** - * 隐形扩展方法名 - * @var array - */ - private static $implicitRules = []; - - /** - * 验证器事件处理类 + * Validator event handling class * @var array */ private $handlers = []; /** - * 验证前需要执行的方法 + * Methods to be executed before validation * @var array */ private $befores = []; /** - * 验证后需要执行的方法 + * Methods to be executed after validation * @var array */ private $afters = []; /** - * 当前进行验证的数据 + * Error Message Provider + * @var MessageProviderInterface + */ + private $messageProvider = null; + + /** + * Data to be validated * @var array */ private $checkData = []; /** - * 创建一个验证器 - * @param array $rules 验证规则 - * @param array $messages 错误消息 - * @param array $customAttributes 字段名称 + * Create a validator + * + * @param array $rules Validation rules + * @param array $messages Error message + * @param array $customAttributes Field Name * @return Validate */ public static function make(array $rules = [], array $messages = [], array $customAttributes = []): Validate @@ -139,7 +95,8 @@ class Validate } /** - * 获取验证器工厂 + * Get Validator Factory + * * @return Factory */ private static function getValidationFactory(): Factory @@ -148,16 +105,19 @@ class Validate } /** - * 自动验证 - * @param array $data 待验证的数据 + * Auto validate + * + * @param array $data Data to be verified * @return array * @throws ValidateException */ public function check(array $data): array { try { + $this->init(); $this->checkData = $data; - $rule = $this->getSceneRules(); + $this->addHandler($this->handler); + $rule = $this->getCheckRules($this->getRules()); if ($this->filled) { $rule = $this->addFilledRule($rule); @@ -188,7 +148,7 @@ class Validate return $data; } catch (ValidationException $e) { - $errors = $this->handlingError($e->errors()); + $errors = $this->getMessageProvider()->handleMessage($e->errors()); $errorMessage = ''; foreach ($errors as $message) { $errorMessage = $message[0]; @@ -200,64 +160,93 @@ class Validate } /** - * 获取当前的验证数据 - * @param string $key - * @param null $default - * @return array|mixed + * Get initial rules provided + * + * @param string|null $sceneName The scene name, or the current scene name if not provided. + * @return array + * @throws ValidateException */ - public function getData(string $key = '', $default = null) + public function getRules(?string $sceneName = ''): array { - if (!empty($key)) { - return Arr::get($this->checkData, $key, $default); + if ('' === $sceneName) { + $sceneName = $this->getCurrentSceneName(); } - return $this->checkData; - } - /** - * 获取当前的验证数据,返回验证集合类型 - * @return Support\Storage\ValidateCollection - */ - public function getValidateData(): Support\Storage\ValidateCollection - { - return validate_collect($this->getData()); - } + if (empty($sceneName)) { + return $this->rule; + } - /** - * 处理错误消息 - * @param array $errors - * @return array - */ - private function handlingError(array $errors): array - { - foreach ($errors as &$errorMessages) { - if (is_array($errorMessages)) { - $errorMessages = array_map([$this, 'replacingFieldsInMessage'], $errorMessages); - } else { - $errorMessages = $this->replacingFieldsInMessage($errorMessages); - } + if (method_exists($this, 'scene' . ucfirst($sceneName))) { + $scene = new ValidateScene($this->rule); + call_user_func([$this, 'scene' . ucfirst($sceneName)], $scene); + $this->handlers = array_merge($this->handlers, $scene->handlers); + $this->afters = array_merge($this->handlers, $scene->afters); + $this->befores = array_merge($this->handlers, $scene->befores); + $this->eventPriority = $scene->eventPriority; + return $scene->getRules(); } - return $errors; - } - /** - * 替换错误消息中的字段 - * @param string $message - * @return string|string[] - */ - private function replacingFieldsInMessage(string $message) - { - if (preg_match_all('/{:(.*?)}/', $message, $matches) > 0) { - foreach ($matches[0] as $index => $pregString) { - $message = str_replace($pregString, Arr::get($this->checkData, $matches[1][$index], ''), $message); + if (isset($this->scene[$sceneName])) { + $sceneRule = $this->scene[$sceneName]; + + # Determine if an event is defined + if (isset($sceneRule['handler'])) { + $handlers = $sceneRule['handler']; + $this->addHandler($handlers); + unset($sceneRule['handler']); + } + + # Methods to be executed before determining the presence or absence of authentication + if (isset($sceneRule['before'])) { + $callback = $sceneRule['before']; + $this->addBefore($callback); + unset($sceneRule['before']); + } + + # Methods to be executed after determining the existence of validation + if (isset($sceneRule['after'])) { + $callback = $sceneRule['after']; + $this->addAfter($callback); + unset($sceneRule['after']); + } + + # Determine if other authentication scenarios are specified for the authentication scenario + if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { + $use = $sceneRule['use']; + if ($use === $sceneName) { + throw new LogicException('The scene used cannot be the same as the current scene.'); + } + unset($sceneRule['use']); + # If the specified `use` is a method + if (method_exists($this, 'use' . ucfirst($use))) { + # Pre-validation, where the values to be passed to the closure are validated according to the specified rules + $data = []; + if (!empty($sceneRule)) { + $randScene = md5(rand(1, 1000000) . time()); + $data = (clone $this)->setScene( + [$randScene => $sceneRule] + )->scene($randScene)->check($this->checkData); + } + + $use = call_user_func([$this, 'use' . ucfirst($use)], $data); + if (is_array($use)) { + return array_intersect_key($this->rule, array_flip($use)); + } + } + return $this->getRules($use); + } else { + return array_intersect_key($this->rule, array_flip($sceneRule)); } } - return $message; + + return $this->rule; } /** - * 处理方法 + * Processing method + * * @param array $data - * @param int $type 类型,1 验证前方法 2 验证后方法 + * @param int $type 1 before method 2 after method * @return array * @throws ValidateException */ @@ -309,9 +298,10 @@ class Validate } /** - * 验证事件处理 - * @param array $data 验证的数据 - * @param string $method 事件名称 + * validate event handling + * + * @param array $data Validated data + * @param string $method Event Name * @return array * @throws ValidateException */ @@ -320,12 +310,13 @@ class Validate if (empty($this->handlers)) { return $data; } - $result = (new ValidateHandler($data, $this->handlers, $this->currentScene))->handle($method); + $result = (new ValidateHandler($data, $this->handlers, $this->getCurrentSceneName()))->handle($method); return $this->handleEventResult($result); } /** - * 处理事件结果 + * Handling of event results + * * @param $result * @return array * @throws ValidateException @@ -334,7 +325,7 @@ class Validate { if (is_string($result)) { if (isset($this->message[$result])) { - $result = $this->replacingFieldsInMessage($this->message[$result]); + $result = $this->getMessageProvider()->handleMessage($this->message[$result]); } throw new ValidateException($result, 403); } elseif (is_array($result)) { @@ -345,11 +336,10 @@ class Validate } /** - * 初始化验证 + * Initialization validate */ private function init() { - $this->checkRule = collect([]); $this->handlers = []; $this->afters = []; $this->befores = []; @@ -357,124 +347,50 @@ class Validate } /** - * 获取当前场景下需要验证的规则 - * @return array + * Set the message provider for the validator. + * + * @param MessageProviderInterface|string|callable $messageProvider + * @return $this * @throws ValidateException */ - private function getSceneRules(): array - { - $this->init(); - $this->addHandler($this->handler); - $this->getScene($this->currentScene); - $this->checkRule->transform(function ($rule, $field) { - if (!is_array($rule) && !$rule instanceof Collection) { - $_rules = collect(explode('|', $rule)); - } else { - $_rules = collect($rule); - } - $_rules->transform(function ($value) use ($field) { - if (is_string($value)) { - # 判断是否为自定义规则 - $ruleClass = $this->getRuleClass($value); - if (false !== $ruleClass) { - # 给自定义规则设置自定义错误消息 - $message = $this->getMessages($field, $value); - if ($message) { - $ruleClass->setMessage($message); - } - return $ruleClass; - } - - return $this->getExtendsRule($value, $field); - } - return $value; - }); - return $_rules; - }); - return $this->checkRule->toArray(); - } - - /** - * 获取扩展规则 - * 由于为了区分多个验证器的相同自定义方法名,对方法名做了处理,此方法为了使规则和处理后的方法名对应上 - * @param string $rule 规则名称 - * @param string|null $field 字段 - * @return string - */ - private function getExtendsRule(string $rule, string $field = null): string + public function setMessageProvider($messageProvider): RuleManager { - list($rule, $param) = $this->getKeyAndParam($rule, false); - - # 取回真实的自定义规则方法名称,以及修改对应的错误消息 - if (array_key_exists($rule, self::$extendName)) { - $ruleName = md5(get_called_class() . $rule); - # 判断是否为自定义规则方法定义了错误消息 - if (null !== $field && isset($this->message[$field . '.' . $rule])) { - $this->message[$ruleName] = $this->message[$field . '.' . $rule]; - } - - $rule = $ruleName; + if (is_string($messageProvider) && is_subclass_of($messageProvider, MessageProviderInterface::class)) { + $this->messageProvider = new $messageProvider(); + } elseif (is_object($messageProvider) && is_subclass_of($messageProvider, MessageProviderInterface::class)) { + $this->messageProvider = $messageProvider; + } elseif (is_callable($messageProvider)) { + $messageProvider = call_user_func($messageProvider); + $this->setMessageProvider($messageProvider); + return $this; } else { - # 如果当前自定义规则中不存在,则判断是否为类方法 - # 如果是类方法,则先注册规则到验证器中,然后再处理对应的错误消息 - if (method_exists($this, 'rule' . ucfirst($rule))) { - self::extend($rule, Closure::fromCallable([$this, 'rule' . ucfirst($rule)])); - - if ('' !== $param) { - $rule = $rule . ':' . $param; - } - - return $this->getExtendsRule($rule, $field); - } + throw new ValidateException('The provided message processor needs to implement the MessageProviderInterface interface'); } - if ('' !== $param) { - $rule = $rule . ':' . $param; - } - return $rule; + return $this; } /** - * 获取规则的名称和参数 - * @param string $value 规则 - * @param bool $parsing 是否解析参数,默认为false - * @return array + * Get the message provider for the validator. + * + * @return MessageProviderInterface */ - private function getKeyAndParam(string $value, bool $parsing = false): array + public function getMessageProvider(): MessageProviderInterface { - $param = ''; - if (false !== strpos($value, ':')) { - $arg = explode(':', $value, 2); - $key = $arg[0]; - if (count($arg) >= 2) { - $param = $arg[1]; - } - } else { - $key = $value; + if (empty($this->messageProvider)) { + $this->messageProvider = new MessageProvider(); } - if ($parsing) { - $param = explode(',', $param); - } - return [$key, $param]; - } - - /** - * 生成错误消息的名称 - * @param string $field 字段 - * @param string $rule 规则 - * @return string - */ - private function makeMessageName(string $field, string $rule): string - { - if (false !== strpos($rule, ':')) { - $rule = substr($rule, 0, strpos($rule, ':')); - } - return $field . '.' . $rule; + $messageProvider = $this->messageProvider; + $messageProvider->setMessage($this->message); + $messageProvider->setCustomAttributes($this->customAttributes); + $messageProvider->setData($this->checkData); + return $messageProvider; } /** - * 添加事件 + * Add Event + * * @param $handlers */ private function addHandler($handlers) @@ -483,7 +399,8 @@ class Validate } /** - * 添加验证前方法 + * Methods to be executed before adding validation + * * @param $callback */ private function addBefore($callback) @@ -492,7 +409,8 @@ class Validate } /** - * 添加验证后方法 + * Add the method that needs to be executed after verification + * * @param $callback */ private function addAfter($callback) @@ -501,8 +419,9 @@ class Validate } /** - * 添加方法 - * @param int $intType 0为事件 1为验证前方法 2为验证后方法 + * Add method + * + * @param int $intType 0 event 1 before 2 after * @param $callback */ private function addCallback(int $intType, $callback) @@ -528,576 +447,13 @@ class Validate if (is_int($classOrMethod)) { $this->$type[] = [$param, []]; } elseif (is_string($classOrMethod)) { - $callbackName = str_replace('s', '', $type); if (is_array($param)) { - $this->$callbackName($classOrMethod, ...$param); + $this->$type[] = [$classOrMethod, $param]; } else { - $this->$callbackName($classOrMethod, $param); - } - } - } - } - } - - /** - * 添加bail规则 - * @param array $rules 原规则 - * @return array - */ - private function addBailRule(array $rules): array - { - foreach ($rules as &$rule) { - if (!in_array('bail', $rule)) { - array_unshift($rule, 'bail'); - } - } - - return $rules; - } - - /** - * 添加filled规则 - * @param array $rules 原规则 - * @return array - */ - private function addFilledRule(array $rules): array - { - $conflictRules = [ - 'filled', 'nullable', 'accepted', 'present', 'required', 'required_if', 'required_unless', 'required_with', - 'required_with_all', 'required_without', 'required_without_all', - ]; - - foreach ($rules as &$rule) { - $rulesName = array_map(function ($value) { - if (is_object($value)) { - // 如果继承了ImplicitRule标记接口 - // 代表此自定义规则想要在属性为空时执行规则对象 - // 所以也不需要添加filled规则,那么就让数组对象里存在一个filled - // 下面的判断就会自动跳过,实际上规则中没有被添加filled规则 - if ($value instanceof ImplicitRule) { - return 'filled'; - } else { - return ''; - } - } - - $ruleName = $this->getKeyAndParam($value)[0]; - - // 此处操作同上 - if (in_array($ruleName, self::$implicitRules)) { - return 'filled'; - } - - return $ruleName; - }, $rule); - - if (empty(array_intersect($conflictRules, $rulesName))) { - array_unshift($rule, 'filled'); - } - } - - return $rules; - } - - /** - * 进入场景 - * @param string|null $name 场景名称 - * @return void - * @throws ValidateException - */ - private function getScene(?string $name = null): void - { - if (empty($name)) { - $this->checkRule = collect($this->rule); - return; - } - # 判断自定义验证场景是否存在 - if (method_exists($this, 'scene' . ucfirst($name))) { - $this->checkRule = collect($this->rule); - call_user_func([$this, 'scene' . ucfirst($name)]); - } elseif (isset($this->scene[$name])) { // 判断验证场景是否存在 - $sceneRule = $this->scene[$name]; - - # 判断是否定义了事件 - if (isset($sceneRule['handler'])) { - $handlers = $sceneRule['handler']; - $this->addHandler($handlers); - unset($sceneRule['handler']); - } - - # 判断是否定义了验证前需要执行的方法 - if (isset($sceneRule['before'])) { - $callback = $sceneRule['before']; - $this->addBefore($callback); - unset($sceneRule['before']); - } - - # 判断是否定义了验证后需要执行的方法 - if (isset($sceneRule['after'])) { - $callback = $sceneRule['after']; - $this->addAfter($callback); - unset($sceneRule['after']); - } - - # 判断验证场景是否指定了其他验证场景 - if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { - $use = $sceneRule['use']; - if ($use === $name || $use === $this->currentScene) { - throw new LogicException('The scene used cannot be the same as the current scene.'); - } - unset($sceneRule['use']); - # 如果指定的use是一个方法 - if (method_exists($this, 'use' . ucfirst($use))) { - # 进行预验证,将需要传给闭包的值按指定规则进行验证 - $data = []; - if (!empty($sceneRule)) { - $randScene = md5(rand(1, 1000000) . time()); - $data = (clone $this)->setScene( - [$randScene => $sceneRule] - )->scene($randScene)->check($this->checkData); + $this->$type[] = [$classOrMethod, [$param]]; } - - $use = call_user_func([$this, 'use' . ucfirst($use)], $data); - if (is_array($use)) { - $this->checkRule = collect($this->rule)->only($use); - return; - } - } - $this->getScene($use); - } else { - $this->checkRule = collect($this->rule)->only($sceneRule); - } - } else { - # 如果验证场景找不到,则默认验证全部规则 - $this->checkRule = collect($this->rule); - } - } - - /** - * 获取自定义规则的实例类 - * - * @param string $ruleName 自定义规则名称 - * @param bool $ruleClassName 是否只获取Class完整命名空间 默认为false - * @return false|mixed|Closure - */ - private function getRuleClass(string $ruleName, bool $ruleClassName = false) - { - list($ruleName, $param) = $this->getKeyAndParam($ruleName, true); - - foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { - $ruleNameSpace = $rulesPath . ucfirst($ruleName); - if (class_exists($ruleNameSpace) && is_subclass_of($ruleNameSpace, BaseRule::class)) { - if ($ruleClassName) { - return $ruleNameSpace; - } else { - return new $ruleNameSpace(...$param); } } } - - return false; - } - - /** - * 注册自定义验证方法 - * - * @param string $rule 规则名称 - * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator - * @param string|null $message 错误消息 - */ - public static function extend(string $rule, $extension, ?string $message = null) - { - self::validatorExtend('', $rule, $extension, $message); - } - - /** - * 注册一个自定义的隐式验证器扩展 - * - * @param string $rule 规则名称 - * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator - * @param string|null $message 错误消息 - */ - public static function extendImplicit(string $rule, $extension, ?string $message = null) - { - self::validatorExtend('Implicit', $rule, $extension, $message); - } - - /** - * 注册一个自定义依赖性验证器扩展 - * - * @param string $rule 规则名称 - * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator - * @param string|null $message 错误消息 - */ - public static function extendDependent(string $rule, $extension, ?string $message = null) - { - self::validatorExtend('Dependent', $rule, $extension, $message); - } - - /** - * 注册自定义验证器扩展 - * @param string $type 类型 - * @param string $rule 规则名称 - * @param Closure|string|array $extension 闭包规则,回调四个值 $attribute, $value, $parameters, $validator - * @param string|null $message 错误消息 - */ - private static function validatorExtend(string $type, string $rule, $extension, ?string $message = null) - { - $ruleName = md5(get_called_class() . $rule); - - if (array_key_exists($rule, self::$extendName)) { - array_push(self::$extendName[$rule], $ruleName); - self::$extendName[$rule] = array_unique(self::$extendName[$rule]); - } else { - self::$extendName[$rule] = [$ruleName]; - } - - # 多个验证器使用了同样的rule会导致后面的方法无法生效 - # 故这里根据命名空间生成一个独一无二的rule名称 - $ruleName = md5(get_called_class() . $rule); - - if (!empty($type)) { - $method = 'extend' . $type; - } else { - $method = 'extend'; - } - - if ('Implicit' === $type) { - self::$implicitRules[] = $ruleName; - } - - self::getValidationFactory()->$method($ruleName, $extension, $message); - } - - /** - * 注册自定义验证方法错误消息 - * @param string $rule 规则名称 - * @param string|Closure $replacer 闭包规则,回调四个值 $message,$attribute,$rule,$parameters - */ - public static function replacer(string $rule, $replacer) - { - if (array_key_exists($rule, self::$extendName)) { - $ruleName = md5(get_called_class() . $rule); - if (in_array($ruleName, self::$extendName[$rule])) { - $rule = $ruleName; - } - } - self::getValidationFactory()->replacer($rule, $replacer); - } - - /** - * 设置验证场景 - * - * @param string $name - * @return $this - */ - public function scene(string $name): Validate - { - $this->currentScene = $name; - return $this; - } - - /** - * 设置事件优先级 - * @param bool $priority - * @return $this - */ - public function setEventPriority(bool $priority): Validate - { - $this->eventPriority = $priority; - return $this; - } - - /** - * 加入事件 - * @param string $handler 事件的完整类名,完整命名空间字符串或者加::class - * @param mixed ...$params 要传递给事件的参数 - * @return $this - */ - public function handler(string $handler, ...$params): Validate - { - $this->handlers[] = [$handler, $params]; - return $this; - } - - /** - * 添加一个验证前的需要执行的方法 - * @param string $callbackName 本类的方法名 - * @param mixed ...$params 要传递给方法的参数 - * @return $this - */ - public function before(string $callbackName, ...$params): Validate - { - $this->befores[] = [$callbackName, $params]; - return $this; - } - - /** - * 添加一个验证后需要执行的方法 - * @param string $callbackName 本类的方法名 - * @param mixed ...$params 要传递给方法的参数 - * @return $this - */ - public function after(string $callbackName, ...$params): Validate - { - $this->afters[] = [$callbackName, $params]; - return $this; - } - - /** - * 指定需要验证的字段列表 - * - * @param array $fields 字段名 - * @return $this - */ - public function only(array $fields): Validate - { - $this->checkRule = $this->checkRule->only($fields); - return $this; - } - - /** - * 添加字段到验证列表中 - * @param string $field - * @return $this - */ - public function addCheckField(string $field): Validate - { - $rule = $this->rule[$field] ?? ''; - $this->checkRule = $this->checkRule->merge([$field => $rule]); - return $this; - } - - /** - * 删除验证列表中的字段 - * @param string $field - * @return $this - */ - public function removeCheckField(string $field): Validate - { - $this->checkRule->forget($field); - return $this; - } - - /** - * 追加某个字段的验证规则 - * - * @param string $field 字段名 - * @param string $rule 验证规则 - * @return $this - */ - public function append(string $field, string $rule): Validate - { - if (isset($this->checkRule[$field])) { - if (is_array($this->checkRule[$field])) { - $this->checkRule[$field] = collect($this->checkRule[$field]); - } - - if ($this->checkRule[$field] instanceof Collection) { - $appendRule = explode('|', $rule); - $this->checkRule[$field] = $this->checkRule[$field]->concat($appendRule); - } else { - if (empty($this->checkRule[$field])) { - $this->checkRule[$field] = $rule; - } else { - $this->checkRule[$field] = $this->checkRule[$field] . '|' . $rule; - } - } - } - - return $this; - } - - /** - * 移除某个字段的验证规则 - * - * @param string $field 字段名 - * @param string|null $rule 验证规则 null 移除所有规则 - * @return $this - */ - public function remove(string $field, ?string $rule = null): Validate - { - $removeRule = $rule; - if (is_string($rule) && false !== strpos($rule, '|')) { - $removeRule = explode('|', $rule); - } - - if (is_array($removeRule)) { - foreach ($removeRule as $rule) { - $this->remove($field, $rule); - } - } else { - if (isset($this->checkRule[$field])) { - if (null === $rule) { - $this->checkRule[$field] = []; - } else { - $rules = $this->checkRule[$field]; - if (is_string($rules)) { - $rules = explode('|', $rules); - $rules = collect($rules); - } - - if (false !== strpos($rule, ':')) { - $rule = substr($rule, 0, strpos($rule, ':')); - } - $rules = $rules->filter(function ($value) use ($rule) { - if (false !== strpos($value, ':')) { - $value = substr($value, 0, strpos($value, ':')); - } - return $value !== $rule; - }); - - $this->checkRule[$field] = $rules; - } - } - } - - return $this; - } - - /** - * 复杂条件验证 - * - * @param string|string[] $attribute 字段 - * @param string|array|BaseRule $rules 规则 - * @param callable $callback 回调方法,方法提供一个{@see ValidateCollection} $data参数,参数为当前验证的数据, - * 返回true则规则生效 - * @return $this - */ - public function sometimes($attribute, $rules, callable $callback): Validate - { - $data = $this->getValidateData(); - $result = call_user_func($callback, $data); - - if (!$result) { - return $this; - } - - if (is_array($rules)) { - $rules = implode('|', $rules); - } - - if (is_array($attribute)) { - foreach ($attribute as $filed) { - $this->append($filed, $rules); - } - } else { - $this->append($attribute, $rules); - } - - return $this; - } - - /** - * 获取验证规则 - * - * @param null $rule 验证字段 - * @return array|mixed|null - */ - public function getRules($rule = null) - { - if (null === $rule) { - return $this->rule; - } - - if (is_array($rule)) { - return collect($this->rule)->only($rule)->toArray(); - } else { - return $this->rule[$rule] ?? null; - } - } - - /** - * 设置验证规则(叠加) - * - * @param array|null $rules [字段 => 规则] 如果$rules为null,则清空全部验证规则 - * @return $this - */ - public function setRules(?array $rules = null): Validate - { - if (is_null($rules)) { - $this->rule = []; - } else { - $this->rule = array_merge($this->rule, $rules); - } - - return $this; - } - - /** - * 获取验证消息 - * - * @param null|string|string[] $key 完整消息Key值 - * @param string|null $rule 如果第一个值为字段名,则第二个值则为规则,否则请留空 - * @return array|mixed|null - */ - public function getMessages($key = null, ?string $rule = null) - { - if (null === $key) { - return $this->message; - } - - if (null !== $rule) { - $messageName = $this->makeMessageName($key, $rule); - } else { - $messageName = $key; - } - - if (is_array($messageName)) { - return collect($this->message)->only($messageName)->toArray(); - } else { - return $this->message[$messageName] ?? null; - } - } - - /** - * 设置错误消息(叠加) - * - * @param array|null $message [字段.规则 => 验证消息] 如果$message为null,则清空全部验证消息 - * @return $this - */ - public function setMessages(?array $message = null): Validate - { - if (is_null($message)) { - $this->message = []; - } else { - $this->message = array_merge($this->message, $message); - } - - return $this; - } - - /** - * 设置字段名称(叠加) - * - * @param array|null $customAttributes [字段 => 名称] 如果$customAttributes为null,则清空全部字段名称 - * @return $this - */ - public function setCustomAttributes(?array $customAttributes = null): Validate - { - if (is_null($customAttributes)) { - $this->customAttributes = []; - } else { - $this->customAttributes = array_merge($this->customAttributes, $customAttributes); - } - - return $this; - } - - /** - * 设置验证场景数据(叠加) - * - * @param array|null $scene [场景 => [字段]] 如果$scene为null,则清空全部验证场景 - * @return $this - */ - public function setScene(?array $scene = null): Validate - { - if (is_null($scene)) { - $this->scene = []; - } else { - $this->scene = array_merge($this->scene, $scene); - } - - return $this; } } diff --git a/tests/Material/ArticleValidate.php b/tests/Material/ArticleValidate.php index c9e6f10..3a33c3e 100644 --- a/tests/Material/ArticleValidate.php +++ b/tests/Material/ArticleValidate.php @@ -12,6 +12,7 @@ namespace W7\Tests\Material; +use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; class ArticleValidate extends Validate @@ -47,18 +48,18 @@ class ArticleValidate extends Validate return true; } - public function sceneEdit() + public function sceneEdit(ValidateScene $scene) { - return $this->only(['id', 'content', 'title']) + return $scene->only(['id', 'content', 'title']) ->append('id', 'max:10000') ->remove('content', 'between') ->remove('title', null) ->append('title', 'required|between:4,50|alpha'); } - public function sceneDynamic() + public function sceneDynamic(ValidateScene $scene) { - return $this->only(['title', 'content']) + return $scene->only(['title', 'content']) ->remove('content', 'between'); } } diff --git a/tests/Material/BaseTestValidate.php b/tests/Material/BaseTestValidate.php index af2dae4..7c4913c 100644 --- a/tests/Material/BaseTestValidate.php +++ b/tests/Material/BaseTestValidate.php @@ -23,7 +23,9 @@ class BaseTestValidate extends TestCase public function __construct($name = null, array $data = [], $dataName = '') { $langPath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'laravel-lang' . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR; - if (!file_exists($langPath . 'locales')) { + if (file_exists($langPath . 'locales')) { + $langPath .= 'locales'; + } else { $langPath .= 'src'; } diff --git a/tests/Material/HandlerDataValidate.php b/tests/Material/HandlerDataValidate.php index 3405789..b0bd5cc 100644 --- a/tests/Material/HandlerDataValidate.php +++ b/tests/Material/HandlerDataValidate.php @@ -12,6 +12,7 @@ namespace W7\Tests\Material; +use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; class HandlerDataValidate extends Validate @@ -33,15 +34,15 @@ class HandlerDataValidate extends Validate 'beforeSetDefaultNameIsError' => ['name', 'before' => 'setDefaultNameIsError'] ]; - public function sceneBeforeHandlerDataScene() + public function sceneBeforeHandlerDataScene(ValidateScene $scene) { - $this->only(['name']) + $scene->only(['name']) ->before('setDefaultName'); } - public function sceneBeforeSetDefaultNameIsErrorScene() + public function sceneBeforeSetDefaultNameIsErrorScene(ValidateScene $scene) { - $this->only(['name']) + $scene->only(['name']) ->before('setDefaultNameIsError'); } diff --git a/tests/Material/Rules/Length.php b/tests/Material/Rules/Length.php new file mode 100644 index 0000000..38c8bba --- /dev/null +++ b/tests/Material/Rules/Length.php @@ -0,0 +1,37 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material\Rules; + +use W7\Validate\Support\Rule\BaseRule; + +/** + * 通过字节的方式来限定长度 + * @package W7\App\Model\Validate\Rules + */ +class Length extends BaseRule +{ + protected $message = ':attribute的长度需为%d个字节'; + + protected $size; + + public function __construct(int $size) + { + $this->size = $size; + $this->messageParam = [$size]; + } + + public function passes($attribute, $value): bool + { + return strlen($value) === $this->size; + } +} diff --git a/tests/Material/Rules/LengthBetween.php b/tests/Material/Rules/LengthBetween.php new file mode 100644 index 0000000..92738b3 --- /dev/null +++ b/tests/Material/Rules/LengthBetween.php @@ -0,0 +1,40 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material\Rules; + +use W7\Validate\Support\Rule\BaseRule; + +/** + * 通过字节的方式来限定长度的合法范围 + * @package W7\App\Model\Validate\Rules + */ +class LengthBetween extends BaseRule +{ + protected $message = ':attribute的长度需为%d~%d字节之间'; + + protected $min; + + protected $max; + + public function __construct(int $min, int $max) + { + $this->min = $min; + $this->max = $max; + $this->messageParam = [$min, $max]; + } + + public function passes($attribute, $value): bool + { + return strlen($value) >= $this->min && strlen($value) <= $this->max; + } +} diff --git a/tests/Test/TestValidateMessage.php b/tests/Test/TestValidateMessage.php new file mode 100644 index 0000000..535fa6c --- /dev/null +++ b/tests/Test/TestValidateMessage.php @@ -0,0 +1,65 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\RuleManager; +use W7\Validate\Support\MessageProvider; + +class TestMessage extends RuleManager +{ + protected $rule = [ + 'user' => 'required|email', + 'pass' => 'required|lengthBetween:6,16', + 'name' => 'required|chs|lengthBetween:2,4', + 'remark' => 'required|alpha_dash', + 'captcha' => 'required|length:4|checkCaptcha', + ]; + + protected $message = [ + 'user.required' => '用户名必须填写', + 'user.email' => '你输入的:{:user},不是有效的:attribute', + 'pass.required' => '密码必须填写' + ]; + + protected $customAttributes = [ + 'user' => '用户名', + 'pass' => '密码', + 'name' => '昵称', + 'remark' => '备注', + 'captcha' => '验证码', + ]; +} + +class TestValidateMessage extends BaseTestValidate +{ + /** @var TestMessage */ + protected $testMessage; + + public function __construct($name = null, array $data = [], $dataName = '') + { + parent::__construct($name, $data, $dataName); + $this->testMessage = new TestMessage(); + } + + public function testGetCustomMessage() + { + $message = (new MessageProvider())->setRuleManager($this->testMessage); + $this->assertEquals('用户名必须填写', $message->getInitialMessage('user', 'required')); + $this->assertEquals('你输入的:{:user},不是有效的:attribute', $message->getInitialMessage('user', 'email')); + + $this->assertEquals('你输入的:123456,不是有效的:attribute', $message->setData([ + 'user' => '123456' + ])->getMessage('user', 'email')); + } +} diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index b45ad6d..bfdf1aa 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -14,11 +14,51 @@ namespace W7\Tests\Test; use W7\Tests\Material\ArticleValidate; use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\Rules\Length; use W7\Validate\Exception\ValidateException; +use W7\Validate\RuleManager; +use W7\Validate\Support\Concerns\SceneInterface; + +class UserRules extends RuleManager +{ + protected $rule = [ + 'user' => 'required|email', + 'pass' => 'required|lengthBetween:6,16', + 'name' => 'required|chs|lengthBetween:2,4', + 'remark' => 'required|alpha_dash', + 'captcha' => 'required|length:4|checkCaptcha', + ]; + + protected $scene = [ + 'login' => ['user', 'pass'], + 'captcha' => ['captcha'] + ]; + + protected $message = [ + 'captcha.checkCaptcha' => '验证码错误' + ]; + + protected function sceneRegister(SceneInterface $scene) + { + return $scene->only(['user', 'pass', 'name', 'remark']) + ->remove('remark', 'required|alpha_dash') + ->append('remark', 'chs'); + } + + protected function sceneRegisterNeedCaptcha(SceneInterface $scene) + { + return $this->sceneRegister($scene)->appendCheckField('captcha'); + } + + public function ruleCheckCaptcha($att, $value): bool + { + return true; + } +} class TestValidateScene extends BaseTestValidate { - protected array $userInput; + protected $userInput; public function __construct($name = null, array $data = [], $dataName = '') { @@ -29,6 +69,71 @@ class TestValidateScene extends BaseTestValidate ]; } + public function testGetAllRule() + { + $this->assertCount(5, (new UserRules())->getRules()); + } + + public function testSceneIsLogin() + { + $userRule = new UserRules(); + + $needRules = [ + 'user' => 'required|email', + 'pass' => 'required|lengthBetween:6,16' + ]; + + $this->assertEquals($needRules, $userRule->scene('login')->getRules()); + $this->assertEquals($needRules, $userRule->getRules('login')); + } + + public function testCustomValidateScene() + { + $userRule = new UserRules(); + $rules = $userRule->scene('register')->getRules(); + + $this->assertCount(4, $rules); + $this->assertArrayHasKey('remark', $rules); + $this->assertFalse(in_array('alpha_dash', $rules['remark'])); + $this->assertTrue(in_array('chs', $rules['remark'])); + + $rules = $userRule->scene('registerNeedCaptcha')->getRules(); + $this->assertCount(5, $rules); + $this->assertArrayHasKey('captcha', $rules); + } + + public function testExtendsRule() + { + $userRule = new UserRules(); + + $rules = $userRule->scene('captcha')->getCheckRules(); + + $this->assertArrayHasKey('captcha', $rules); + $haveRequiredRule = $haveCustomRule = $haveExtendRule = $extendRuleName = false; + foreach ($rules['captcha'] as $rule) { + switch ($rule) { + case 'required': + $haveRequiredRule = true; + break; + case $rule instanceof Length: + $haveCustomRule = true; + break; + case 32 === strlen($rule): + $haveExtendRule = true; + $extendRuleName = $rule; + break; + } + } + + $this->assertTrue($haveRequiredRule); + $this->assertTrue($haveCustomRule); + $this->assertTrue($haveExtendRule); + + $messages = $userRule->getMessages(); + + $this->assertEquals('验证码错误', $messages[$extendRuleName]); + } + /** * @test 测试没有指定验证场景的情况 * @throws ValidateException @@ -50,7 +155,7 @@ class TestValidateScene extends BaseTestValidate $data = $v->scene('add')->check($this->userInput); $this->assertEquals('内容', $data['content']); } - + /** * @test 测试自定义验证场景 edit * @throws ValidateException @@ -61,7 +166,7 @@ class TestValidateScene extends BaseTestValidate $this->expectException(ValidateException::class); $validate->scene('edit')->check($this->userInput); } - + /** * @test 测试Use自定义验证场景 save * @throws ValidateException -- Gitee From ab3221407cb852b0e7f082f1c19772e64464169d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 13 May 2021 17:08:56 +0800 Subject: [PATCH 073/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E4=BA=86=E8=87=AA=E5=AE=9A=E4=B9=89=E6=89=A9=E5=B1=95?= =?UTF-8?q?=E8=A7=84=E5=88=99=E7=9A=84=E6=B6=88=E6=81=AF=EF=BC=8C=E4=BD=86?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E4=B8=8D=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 2 +- tests/Test/TestValidateScene.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index c5f3c18..4dd60df 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -278,7 +278,7 @@ class RuleManager $ruleName = md5(get_called_class() . $rule); # Determine if an error message is defined for a custom rule method if (null !== $field && isset($this->message[$field . '.' . $rule])) { - $this->message[$ruleName] = $this->message[$field . '.' . $rule]; + $this->message[$field . '.' . $ruleName] = $this->message[$field . '.' . $rule]; } $rule = $ruleName; diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index bfdf1aa..707a8d8 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -131,7 +131,7 @@ class TestValidateScene extends BaseTestValidate $messages = $userRule->getMessages(); - $this->assertEquals('验证码错误', $messages[$extendRuleName]); + $this->assertEquals('验证码错误', $messages['captcha.' . $extendRuleName]); } /** -- Gitee From 60d8329639afcdac585eb979c45cfc07f870a896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 13 May 2021 17:24:35 +0800 Subject: [PATCH 074/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d552854..7d25a00 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 软擎验证扩展 +# 增强表单验证 为具体的验证场景或者数据表定义好验证器类,调用验证类的check方法即可完成验证,然后你将得到一个安全可用的数据。 ## 说明 -- Gitee From 3527e3dcdeefd4872b2e11861a359ea85da625a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 14 May 2021 17:02:09 +0800 Subject: [PATCH 075/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7d25a00..c98cbd1 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,20 @@ # 增强表单验证 -为具体的验证场景或者数据表定义好验证器类,调用验证类的check方法即可完成验证,然后你将得到一个安全可用的数据。 +一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 ## 说明 此验证基于Laravel的Validator验证器,可用于Laravel,软擎等依赖于illuminate/validation的项目中,此验证器做了如下扩展: - - 可通过类的方式定义一个[验证器](https://v.neww7.com/Validate.html) - - 增加[验证场景](https://v.neww7.com/Scene.html) - - 增加[场景事件处理](https://v.neww7.com/Event.html) - - 修改了[自定义验证规则](https://v.neww7.com/Rule.html) - - [自定义消息](https://v.neww7.com/Message.html) 增加了对内容的引用 - - 继承集合类增加一个[验证集合](https://v.neww7.com/Collection.html) + - 可通过类的方式定义一个[验证器](https://v.neww7.com/3/Validate.html) + - 增加[验证场景](https://v.neww7.com/3/Scene.html) + - 增加[场景事件处理](https://v.neww7.com/3/Event.html) + - 增加[规则管理器](#),你可以单独的它 + - 修改了[自定义验证规则](https://v.neww7.com/3/Rule.html) + - [自定义消息](https://v.neww7.com/3/Message.html) 增加了对内容的引用等 + - 继承集合类增加一个[验证集合](https://v.neww7.com/3/Collection.html) 等...使您的验证只需要在验证器中全部都可以完成 -> 此文档只说明与Laravel的Validator验证器不同的地方,完整Laravel Validator文档可查看:[完整文档](https://learnku.com/docs/laravel/6.x/validation/5144) +> 验证器支持Laravel的内置规则,内置规则文档可查看[规则文档](https://learnku.com/docs/laravel/7.x/validation/5144#c58a91) ## 安装 使用composer命令 -- Gitee From e3e961af9f29772c477ebc9fbb6e50ffef872a53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 14 May 2021 17:12:14 +0800 Subject: [PATCH 076/152] =?UTF-8?q?[D]=20=E9=AA=8C=E8=AF=81=E5=99=A8?= =?UTF-8?q?=E9=9B=86=E5=90=88=E5=88=A0=E9=99=A4=E4=BA=86=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Event/ValidateEventAbstract.php | 21 +- src/Support/Event/ValidateEventInterface.php | 14 ++ src/Support/Rule/BaseRule.php | 4 +- src/Support/Storage/ValidateCollection.php | 207 ++----------------- src/Support/Storage/ValidateConfig.php | 79 ++++--- src/Support/Storage/ValidateFactory.php | 6 +- tests/Test/TestValidateCollection.php | 24 --- 7 files changed, 92 insertions(+), 263 deletions(-) diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index 6ca2693..8619511 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -17,35 +17,26 @@ use Closure; abstract class ValidateEventAbstract implements ValidateEventInterface { /** - * 当前验证场景 + * Current validation scenarios * @var ?string */ protected $sceneName; - /** - * 场景验证前 - * @param array $data 用户输入的数据 - * @param Closure $next - * @return mixed - */ + /** @inheritDoc */ public function beforeValidate(array $data, Closure $next) { return $next($data); } - - /** - * 场景验证后 - * @param array $data 验证后的数据 - * @param Closure $next - * @return mixed - */ + + /** @inheritDoc */ public function afterValidate(array $data, Closure $next) { return $next($data); } /** - * 写入当前的验证场景名称 + * Write the name of the current validation scenario + * * @param string|null $sceneName * @return $this */ diff --git a/src/Support/Event/ValidateEventInterface.php b/src/Support/Event/ValidateEventInterface.php index 58b05f5..346f99a 100644 --- a/src/Support/Event/ValidateEventInterface.php +++ b/src/Support/Event/ValidateEventInterface.php @@ -16,6 +16,20 @@ use Closure; interface ValidateEventInterface { + /** + * Methods implemented prior to validation + * + * @param array $data + * @param Closure $next + * @return mixed + */ public function beforeValidate(array $data, Closure $next); + + /** + * Methods implemented after validation + * @param array $data Validated data + * @param Closure $next + * @return mixed + */ public function afterValidate(array $data, Closure $next); } diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index 7005034..e56f852 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -15,13 +15,13 @@ namespace W7\Validate\Support\Rule; abstract class BaseRule implements RuleInterface { /** - * 错误消息,支持format字符串 + * Error messages, support for format strings * @var string */ protected $message = ''; /** - * 用于format错误消息的参数 + * Parameters for format error messages * @var array */ protected $messageParam = []; diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 7dea08c..2851f9a 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -18,126 +18,13 @@ use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\HigherOrderWhenProxy; use Illuminate\Support\Str; -use W7\Validate\Exception\CollectionException; class ValidateCollection extends Collection { /** - * @var string|null - */ - private $paramType; - - /** - * 将下一次取出的值强制转为int类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function int(): ValidateCollection - { - $this->paramType = 'int'; - return $this; - } - - /** - * 将下一次取出的值强制转为float类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function float(): ValidateCollection - { - $this->paramType = 'float'; - return $this; - } - - /** - * 将下一次取出的值强制转为string类型 + * Determine if an item exists in the collection by key. * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function string(): ValidateCollection - { - $this->paramType = 'string'; - return $this; - } - - /** - * 将下一次取出的值强制转为array类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function array(): ValidateCollection - { - $this->paramType = 'array'; - return $this; - } - - /** - * 将下一次取出的值强制转为object类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function object(): ValidateCollection - { - $this->paramType = 'object'; - return $this; - } - - /** - * 将下一次取出的值强制转为bool类型 - * - * @see get 获取指定字段的值 - * @see pop 移除并返回集合的最后一个集合项 - * @see pull 移除并返回集合的第一个集合项 - * @see shift 移除并返回集合的第一个集合项 - * - *

此类型转换对上诉方法有效

- * 请注意,如果你的值不支持强制转换,会抛出CollectionException异常 - * @return $this - */ - public function bool(): ValidateCollection - { - $this->paramType = 'bool'; - return $this; - } - - /** - * 判断集合中是否存在指定的字段 - * @param mixed $key 要验证的字段 + * @param mixed $key * @return bool */ public function has($key): bool @@ -154,10 +41,11 @@ class ValidateCollection extends Collection } /** - * 当指定字段存在时执行 - * @param mixed $key 要验证的字段 - * @param callable $callback 存在时执行 - * @param callable|null $default 不存在时执行 + * Execute when the specified field exists + * + * @param mixed $key Fields to be validated + * @param callable $callback Methods of execution + * @param callable|null $default Methods to execute when not present * @return HigherOrderWhenProxy|mixed|ValidateCollection */ public function whenHas($key, callable $callback, callable $default = null) @@ -166,10 +54,11 @@ class ValidateCollection extends Collection } /** - * 当指定字段不存在时执行 - * @param mixed $key 要验证的字段 - * @param callable $callback 不存在时执行 - * @param callable|null $default 存在时执行 + * Execute when the specified field does not exist + * + * @param mixed $key Fields to be validated + * @param callable $callback Methods to execute when not present + * @param callable|null $default Methods of execution * @return HigherOrderWhenProxy|mixed|ValidateCollection */ public function whenNotHas($key, callable $callback, callable $default = null) @@ -178,11 +67,11 @@ class ValidateCollection extends Collection } /** - * 获取指定字段的值 - * @param mixed $key 字段名称 - * @param mixed|Closure|null $default 默认值 + * Get an item from the collection by key. + * + * @param mixed $key Field Name + * @param mixed|Closure|null $default Default Value * @return array|ArrayAccess|mixed - * @throws CollectionException */ public function get($key, $default = null) { @@ -228,70 +117,14 @@ class ValidateCollection extends Collection $value = parent::get($key, $default); } - return $this->typeConversion($value); - } - - /** - * 移除并返回集合的最后一个集合项 - * @return mixed - * @throws CollectionException - */ - public function pop() - { - return $this->typeConversion(parent::pop()); - } - - /** - * 移除并返回集合的第一个集合项 - * @return mixed - * @throws CollectionException - */ - public function shift() - { - return $this->typeConversion(parent::shift()); - } - - /** - * 将指定键对应的值从集合中移除并返回 - * @param mixed $key 字段名称 - * @param null $default 默认值 - * @return mixed - * @throws CollectionException - */ - public function pull($key, $default = null) - { - $value = parent::pull($key, $default); - return $this->typeConversion($value); - } - - /** - * 将值转为指定类型 - * @param $value - * @return mixed - * @throws CollectionException - */ - private function typeConversion($value) - { - if (!empty($this->paramType)) { - $error = null; - set_error_handler(function ($type, $msg) use (&$error) { - $error = $msg; - }); - settype($value, $this->paramType); - restore_error_handler(); - $this->paramType = null; - if (!empty($error)) { - throw new CollectionException($error); - } - } - return $value; } /** - * 在集合中写入指定的值 - * @param mixed $key 要写入的字段 - * @param mixed $value 要写入的值 + * Write the specified value in the collection + * + * @param mixed $key + * @param mixed $value * @return $this */ public function set($key, $value): ValidateCollection diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 868daf1..8202425 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -26,50 +26,50 @@ use RuntimeException; final class ValidateConfig { /** - * 自定义规则命名空间前缀 + * Custom rules namespace prefixes * @var array */ protected $rulesPath = []; /** - * 自动加载验证器规则 + * Automatic loading of validator rules * @var array */ protected $autoValidatePath = []; /** - * 翻译器 + * Translator * @var Translator */ protected $translator; /** - * 容器 + * Containers * @var Container */ protected $container; /** - * 验证器工厂 + * Validator Factory * @var Factory */ protected $factory; /** - * 存在验证器 + * Presence Validator * @var PresenceVerifierInterface */ protected $verifier; /** - * 框架类型 + * Frame Type * 1 Laravel 2 Rangine * @var int */ protected $framework = 0; /** - * 验证器具体关联 + * Validator specific association * @var array */ protected $validateLink = []; @@ -86,7 +86,8 @@ final class ValidateConfig } /** - * 设置框架类型 + * Set the frame type + * * @param int $type 1 Laravel 2 Rangine */ public function setFramework(int $type): ValidateConfig @@ -96,7 +97,8 @@ final class ValidateConfig } /** - * 设置验证器工厂 + * Provide validator factory + * * @param Factory $factory * @return ValidateConfig */ @@ -107,7 +109,8 @@ final class ValidateConfig } /** - * 获取验证器工厂 + * Get Validator Factory + * * @return Factory */ public function getFactory(): Factory @@ -136,7 +139,8 @@ final class ValidateConfig } /** - * 设置存在验证器的实现。 + * Set the presence verifier implementation. + * * @param PresenceVerifierInterface $presenceVerifier * @return $this */ @@ -147,7 +151,8 @@ final class ValidateConfig } /** - * 获取存在验证器 + * Get presence verifier + * * @return PresenceVerifierInterface|null */ private function getPresenceVerifier(): ?PresenceVerifierInterface @@ -156,7 +161,8 @@ final class ValidateConfig } /** - * 提供容器 + * Provide containers + * * @param Container $container * @return ValidateConfig */ @@ -167,7 +173,8 @@ final class ValidateConfig } /** - * 获取容器 + * Get container + * * @return Container|null */ private function getContainer(): ?Container @@ -176,7 +183,8 @@ final class ValidateConfig } /** - * 提供翻译器 + * Provide translator + * * @param Translator $translator * @return $this */ @@ -187,7 +195,8 @@ final class ValidateConfig } /** - * 获取翻译器 + * Get Translator + * * @return Translator */ private function getTranslator(): Translator @@ -209,9 +218,10 @@ final class ValidateConfig } /** - * 设置自动加载验证器规则 - * @param string $controllerPath 控制器路径 - * @param string $validatePath 验证器路径 + * Set up auto-load validator rules + * + * @param string $controllerPath Controller path + * @param string $validatePath Validator path * @return $this */ public function setAutoValidatePath(string $controllerPath, string $validatePath): ValidateConfig @@ -229,11 +239,12 @@ final class ValidateConfig } /** - * 设置验证器关联 - * @param string|string[] $controller

控制器完整命名空间

- * 如需指定方法,请传数组,第二个元素为方法名 - * @param string|string[] $validate

验证器完整命名空间

- * 如需指定场景,请传数组,第二个元素为场景名 + * Set Validator Association + * + * @param string|string[] $controller Controller namespace + * To specify a method, pass an array with the second element being the method name + * @param string|string[] $validate Validator namespace + * To specify a scene, pass an array with the second element being the scene name * @return $this */ public function setValidateLink($controller, $validate): ValidateConfig @@ -242,7 +253,7 @@ final class ValidateConfig $controllers = $controller; $controller = $controllers[0]; $method = $controllers[1]; - # 数组中不可以存在 “\” 符号 + # The "\" symbol must not be present in the array $controller = md5($controller); if (count($controllers) >= 2) { if (isset($this->validateLink[$controller])) { @@ -271,8 +282,9 @@ final class ValidateConfig } /** - * 获取验证器具体关联 - * @param string|null $controller 验证器完整命名空间 + * Get validator specific associations + * + * @param string|null $controller Validator full namespace * @return array */ public function getValidateLink(?string $controller = null): array @@ -284,8 +296,9 @@ final class ValidateConfig } /** - * 设置自定义规则命名空间前缀,如设置多个则全部生效 - * @param string $rulesPath 自定义规则命名空间前缀 + * Set the custom rules namespace prefix, If more than one exists, they all take effect + * + * @param string $rulesPath Custom rules namespace prefixes * @return $this */ public function setRulesPath(string $rulesPath): ValidateConfig @@ -296,7 +309,8 @@ final class ValidateConfig } /** - * 获取自定义规则命名空间前缀 + * Get custom rules namespace prefixes + * * @return array */ public function getRulePath(): array @@ -305,7 +319,8 @@ final class ValidateConfig } /** - * 获取自动加载验证器规则 + * Get auto-load validator rules + * * @return array */ public function getAutoValidatePath(): array diff --git a/src/Support/Storage/ValidateFactory.php b/src/Support/Storage/ValidateFactory.php index b8ae91b..920c182 100644 --- a/src/Support/Storage/ValidateFactory.php +++ b/src/Support/Storage/ValidateFactory.php @@ -24,7 +24,7 @@ class ValidateFactory $validateLink = ValidateConfig::instance()->getValidateLink($controller); if (!empty($validateLink)) { - # 为指定的控制器方法指定了验证器 + # Specified validator for the specified controller method if (isset($validateLink[$scene]) || isset($validateLink['!__other__'])) { if (isset($validateLink['!__other__'])) { $method = '!__other__'; @@ -32,7 +32,7 @@ class ValidateFactory $method = $scene; } - # 为指定的验证器指定了验证场景 + # Specifies the validation scenario for the specified validator if (is_array($validateLink[$method])) { if (count($validateLink[$method]) >= 2) { $validate = $validateLink[$method][0]; @@ -47,7 +47,7 @@ class ValidateFactory } if (false === $haveLink) { - # 处理指定了路径的控制器 + # Handles controllers with specified paths $controllerPath = ''; $validatePath = ''; foreach (ValidateConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { diff --git a/tests/Test/TestValidateCollection.php b/tests/Test/TestValidateCollection.php index df8d2de..40c3933 100644 --- a/tests/Test/TestValidateCollection.php +++ b/tests/Test/TestValidateCollection.php @@ -54,30 +54,6 @@ class TestValidateCollection extends BaseTestValidate ], validate_collect($data)->get('*.vendor')); } - public function testTypeConversion() - { - $data = [ - 'age' => '20' - ]; - - $this->assertEquals(20, validate_collect($data)->int()->get('age')); - $this->assertEquals([20], validate_collect($data)->array()->get('age')); - $this->assertEquals(true, validate_collect($data)->bool()->get('age')); - $this->assertEquals('20', validate_collect($data)->string()->get('age')); - - $data = [ - 'age' => '20.05' - ]; - - $this->assertEquals(20, validate_collect($data)->int()->get('age')); - $this->assertEquals(20.05, validate_collect($data)->float()->get('age')); - $data = [ - 'age' => 20 - ]; - - $this->assertEquals('20', validate_collect($data)->string()->get('age')); - } - public function testShift() { $data = validate_collect([1, 2, 3, 4]); -- Gitee From 412d22fb5868fa2258c903f9a2f7b7200842e1e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 18 May 2021 19:09:39 +0800 Subject: [PATCH 077/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E9=80=9A=E8=BF=87=E9=9D=99=E6=80=81=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E8=B0=83=E7=94=A8=E9=AA=8C=E8=AF=81=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E6=9D=A5=E8=BF=94=E5=9B=9E=E8=A7=84=E5=88=99=EF=BC=8C?= =?UTF-8?q?=E6=B6=88=E6=81=AF=EF=BC=8C=E8=87=AA=E5=AE=9A=E4=B9=89=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=20[A]=20=E5=A2=9E=E5=8A=A0getRules=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E8=8E=B7=E5=8F=96=E8=A7=84=E5=88=99=20[A]=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0getMessages=E6=96=B9=E6=B3=95=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E8=8E=B7=E5=8F=96=E9=94=99=E8=AF=AF=E6=B6=88=E6=81=AF?= =?UTF-8?q?=20[A]=20=E5=A2=9E=E5=8A=A0=E9=83=A8=E5=88=86=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=20[U]=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=8E=B7=E5=8F=96=E5=8E=9F=E5=A7=8B=E8=A7=84=E5=88=99?= =?UTF-8?q?=E7=9A=84=E6=96=B9=E6=B3=95=E4=B8=BAgetInitialRules=20[U]=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9getCustomAttributes=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E8=8E=B7=E5=8F=96=E6=8C=87=E5=AE=9A=E7=9A=84?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 178 +++++++++++++++++++++------- src/Validate.php | 18 +-- tests/Material/UserRulesManager.php | 63 ++++++++++ tests/Test/TestHandlerFunction.php | 13 +- tests/Test/TestRuleManagerGet.php | 62 ++++++++++ tests/Test/TestRuleManagerScene.php | 86 ++++++++++++++ tests/Test/TestValidateScene.php | 105 ---------------- 7 files changed, 361 insertions(+), 164 deletions(-) create mode 100644 tests/Material/UserRulesManager.php create mode 100644 tests/Test/TestRuleManagerGet.php create mode 100644 tests/Test/TestRuleManagerScene.php diff --git a/src/RuleManager.php b/src/RuleManager.php index 4dd60df..752e533 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -93,7 +93,7 @@ class RuleManager * @param string|null $sceneName The scene name, or the current scene name if not provided. * @return array */ - public function getRules(?string $sceneName = ''): array + public function getInitialRules(?string $sceneName = ''): array { if ('' === $sceneName) { $sceneName = $this->currentScene; @@ -125,7 +125,7 @@ class RuleManager public function getCheckRules(?array $rules = null): array { if (is_null($rules)) { - $rules = $this->getRules(); + $rules = $this->getInitialRules(); } $rulesFields = array_keys($rules); $rule = array_map(function ($rules, $field) { @@ -137,7 +137,7 @@ class RuleManager if (is_string($ruleName)) { $ruleClass = $this->getRuleClass($ruleName); if (false !== $ruleClass) { - if (!empty($message = $this->getMessages($field, $ruleName))) { + if (!empty($message = $this->getMessage($field, $ruleName))) { $ruleClass->setMessage($message); } return $ruleClass; @@ -273,19 +273,19 @@ class RuleManager { list($rule, $param) = Common::getKeyAndParam($ruleName, false); - # Retrieve the real custom rule method name, and modify the corresponding error message + // Retrieve the real custom rule method name, and modify the corresponding error message if (array_key_exists($rule, self::$extendName)) { $ruleName = md5(get_called_class() . $rule); - # Determine if an error message is defined for a custom rule method + // Determine if an error message is defined for a custom rule method if (null !== $field && isset($this->message[$field . '.' . $rule])) { $this->message[$field . '.' . $ruleName] = $this->message[$field . '.' . $rule]; } $rule = $ruleName; } else { - # If it does not exist in the current custom rule, determine if it is a class method - # If it is a class method, register the rule to the rule manager first, - # and then process the corresponding error message + // If it does not exist in the current custom rule, determine if it is a class method + // If it is a class method, register the rule to the rule manager first, + // and then process the corresponding error message if (method_exists($this, 'rule' . ucfirst($rule))) { self::extend($rule, Closure::fromCallable([$this, 'rule' . ucfirst($rule)])); @@ -400,6 +400,27 @@ class RuleManager return $this; } + /** + * Get the specified rule + * + * @param string|string[]|null $field Field name or array of field names.If $field is null, then return all rules + * If a scene value is set, the specified rule is retrieved from the current scene. + * + * @param string $sceneName Scene name, If this value is not provided, the current scene will be the default. + * If you want to ignore the scene, please provide the value null + * @return array + */ + public function getRules($field = null, string $sceneName = ''): array + { + $rules = $this->getInitialRules($sceneName); + if (null === $field) { + return $rules; + } + + $field = is_array($field) ? $field : [$field]; + return array_intersect_key($rules, array_flip($field)); + } + /** * Set the Message(overlay) * @@ -426,16 +447,13 @@ class RuleManager *

If you have defined an extension rule using the {@see RuleManager}, * you need to call the `getCheckRules` method first before calling this method. * Otherwise the error message may not match the extension rule name.

- * @param string|null $key Full message key,if $keys is null,then get all messages + * + * @param string $key Full message key * @param string|null $rule If the first value is a field name, the second value is a rule, otherwise leave it blank * @return array|string|null */ - public function getMessages(?string $key = null, ?string $rule = null) + protected function getMessage(string $key, ?string $rule = null) { - if (null === $key) { - return $this->message; - } - if (null !== $rule) { $messageName = Common::makeMessageName($key, $rule); } else { @@ -445,6 +463,50 @@ class RuleManager return $this->message[$messageName] ?? ''; } + /** + * Get the defined error message + * + * @param string|string[]|null $key Full message key or field name or array of fields + * + * @param string|null $rule If $key is a field name string and this parameter is filled in with the + * corresponding rule under that field, then this method returns the message corresponding to $key$.rule. + * + * When this parameter is provided and $key is a string, the $subMessage parameter fails + * + * @param bool $subMessage Whether to retrieve all error messages under the specified field, default is false + * + * When this parameter is true, the $rule parameter is disabled + * @return array|mixed|string + */ + public function getMessages($key = null, ?string $rule = null, bool $subMessage = false) + { + if (null === $key) { + return $this->message; + } + if (null !== $rule && is_string($key)) { + $key = Common::makeMessageName($key, $rule); + return $this->message[$key] ?? ''; + } + + if ($subMessage) { + $fields = is_array($key) ? $key : [$key]; + return array_filter($this->message, function ($value, $key) use ($fields) { + foreach ($fields as $field) { + if (0 === strrpos($key, $field)) { + return true; + } + } + return false; + }, ARRAY_FILTER_USE_BOTH); + } + + if (is_array($key)) { + return array_intersect_key($this->message, array_flip($key)); + } + + return $this->message[$key] ?? ''; + } + /** * Set the custom attributes(overlay) * @@ -463,46 +525,74 @@ class RuleManager } /** - * Get array of custom attribute names. + * Get array of custom attribute. + * + * @param null|string|array $fields Field name or array of fields, or if null, return all custom attribute * @return array */ - public function getCustomAttributes(): array + public function getCustomAttributes($fields = null): array { - return $this->customAttributes; + if (null === $fields) { + return $this->customAttributes; + } + + $fields = is_array($fields) ? $fields : [$fields]; + + return array_intersect_key($this->customAttributes, array_flip($fields)); } - public static function get($fields = null, $initial = true): array + /** + * Get rules, error messages and custom attribute + * + * Note: This method is not affected by the validate {@see scene} + * + * @param null|string|array $fields Field name or array of fields, or if null, return all + * @param bool $initial Whether to get the original rule, default is true + * @return array Returns three arrays of rules, error messages, and custom attribute + */ + public static function get($fields = null, bool $initial = true): array { - $validate = new static(); - if (null === $fields) { - $rules = $validate->getRules(null); - if (!$initial) { - $rules = $validate->getCheckRules($rules); - } - $message = $validate->getMessages(); - $customAttributes = $validate->getCustomAttributes(); - } else { - if (!is_array($fields)) { - $fields = [$fields]; - } + $validate = new static(); + $rules = $validate->getRules($fields); + $message = $validate->getMessages($fields, null, true); + $customAttributes = $validate->getCustomAttributes($fields); - $rules = array_intersect_key($validate->getRules(null), array_flip($fields)); - if (!$initial) { - $rules = $validate->getCheckRules($rules); - } + if (!$initial) { + $rules = $validate->getCheckRules($rules); + } - $message = array_filter($validate->getMessages(), function ($value, $key) use ($fields) { - foreach ($fields as $field) { - if (0 === strrpos($key, $field)) { - return true; - } - } - return false; - }, ARRAY_FILTER_USE_BOTH); + return [$rules, $message, $customAttributes]; + } - $customAttributes = array_intersect_key($validate->getCustomAttributes(), array_flip($fields)); + /** + * Get rules, error messages and custom attribute by scene name + * + * @param string $sceneName + * @param bool $initial Whether to get the original rule, default is true + * @return array + */ + protected static function getBySceneName(string $sceneName, bool $initial = true): array + { + $validate = new static(); + $rules = $validate->getInitialRules($sceneName); + $fields = array_keys($rules); + $message = $validate->getMessages($fields, null, true); + $customAttributes = $validate->getCustomAttributes($fields); + if (false === $initial) { + $rules = $validate->getCheckRules($rules); } - return [$rules, $message, $customAttributes]; } + + public function __call($name, $arguments) + { + $initial = !(count($arguments) > 0 && false === $arguments[0]); + return $this->getBySceneName($name, $initial); + } + + public static function __callStatic($name, $arguments) + { + $initial = !(count($arguments) > 0 && false === $arguments[0]); + return self::getBySceneName($name, $initial); + } } diff --git a/src/Validate.php b/src/Validate.php index e7fd5f8..3b0d4cb 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -117,7 +117,7 @@ class Validate extends RuleManager $this->init(); $this->checkData = $data; $this->addHandler($this->handler); - $rule = $this->getCheckRules($this->getRules()); + $rule = $this->getCheckRules($this->getInitialRules()); if ($this->filled) { $rule = $this->addFilledRule($rule); @@ -166,7 +166,7 @@ class Validate extends RuleManager * @return array * @throws ValidateException */ - public function getRules(?string $sceneName = ''): array + public function getInitialRules(?string $sceneName = ''): array { if ('' === $sceneName) { $sceneName = $this->getCurrentSceneName(); @@ -189,37 +189,37 @@ class Validate extends RuleManager if (isset($this->scene[$sceneName])) { $sceneRule = $this->scene[$sceneName]; - # Determine if an event is defined + // Determine if an event is defined if (isset($sceneRule['handler'])) { $handlers = $sceneRule['handler']; $this->addHandler($handlers); unset($sceneRule['handler']); } - # Methods to be executed before determining the presence or absence of authentication + // Methods to be executed before determining the presence or absence of authentication if (isset($sceneRule['before'])) { $callback = $sceneRule['before']; $this->addBefore($callback); unset($sceneRule['before']); } - # Methods to be executed after determining the existence of validation + // Methods to be executed after determining the existence of validation if (isset($sceneRule['after'])) { $callback = $sceneRule['after']; $this->addAfter($callback); unset($sceneRule['after']); } - # Determine if other authentication scenarios are specified for the authentication scenario + // Determine if other authentication scenarios are specified for the authentication scenario if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { $use = $sceneRule['use']; if ($use === $sceneName) { throw new LogicException('The scene used cannot be the same as the current scene.'); } unset($sceneRule['use']); - # If the specified `use` is a method + // If the specified `use` is a method if (method_exists($this, 'use' . ucfirst($use))) { - # Pre-validation, where the values to be passed to the closure are validated according to the specified rules + // Pre-validation, where the values to be passed to the closure are validated according to the specified rules $data = []; if (!empty($sceneRule)) { $randScene = md5(rand(1, 1000000) . time()); @@ -233,7 +233,7 @@ class Validate extends RuleManager return array_intersect_key($this->rule, array_flip($use)); } } - return $this->getRules($use); + return $this->getInitialRules($use); } else { return array_intersect_key($this->rule, array_flip($sceneRule)); } diff --git a/tests/Material/UserRulesManager.php b/tests/Material/UserRulesManager.php new file mode 100644 index 0000000..5e49684 --- /dev/null +++ b/tests/Material/UserRulesManager.php @@ -0,0 +1,63 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material; + +use W7\Validate\RuleManager; +use W7\Validate\Support\Concerns\SceneInterface; + +class UserRulesManager extends RuleManager +{ + protected $rule = [ + 'user' => 'required|email', + 'pass' => 'required|lengthBetween:6,16', + 'name' => 'required|chs|lengthBetween:2,4', + 'remark' => 'required|alpha_dash', + 'captcha' => 'required|length:4|checkCaptcha', + ]; + + protected $scene = [ + 'login' => ['user', 'pass'], + 'captcha' => ['captcha'] + ]; + + protected $customAttributes = [ + 'user' => '用户名', + 'pass' => '密码', + 'name' => '昵称', + 'remark' => '备注', + 'captcha' => '验证码', + ]; + + protected $message = [ + 'captcha.checkCaptcha' => '验证码错误', + 'user.email' => '用户名必须为邮箱', + 'pass.lengthBetween' => '密码长度错误' + ]; + + protected function sceneRegister(SceneInterface $scene) + { + return $scene->only(['user', 'pass', 'name', 'remark']) + ->remove('remark', 'required|alpha_dash') + ->append('remark', 'chs'); + } + + protected function sceneRegisterNeedCaptcha(SceneInterface $scene) + { + return $this->sceneRegister($scene)->appendCheckField('captcha'); + } + + public function ruleCheckCaptcha($att, $value): bool + { + return true; + } +} diff --git a/tests/Test/TestHandlerFunction.php b/tests/Test/TestHandlerFunction.php index fe90b89..b9f59e9 100644 --- a/tests/Test/TestHandlerFunction.php +++ b/tests/Test/TestHandlerFunction.php @@ -14,12 +14,13 @@ namespace W7\Tests\Test; use W7\Tests\Material\HandlerDataValidate; use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Exception\ValidateException; class TestHandlerFunction extends BaseTestValidate { /** * @test 测试在after中进行最后的验证 - * @throws \W7\Validate\Exception\ValidateException + * @throws ValidateException */ public function testAfterRule() { @@ -34,7 +35,7 @@ class TestHandlerFunction extends BaseTestValidate /** * @test 测试在after方法中对数据进行处理 - * @throws \W7\Validate\Exception\ValidateException + * @throws ValidateException */ public function testAfterAddData() { @@ -49,7 +50,7 @@ class TestHandlerFunction extends BaseTestValidate /** * @test 测试在before方法中对值设定一个默认值 - * @throws \W7\Validate\Exception\ValidateException + * @throws ValidateException */ public function testBeforeHandlerData() { @@ -66,7 +67,7 @@ class TestHandlerFunction extends BaseTestValidate /** * @test 测试在before方法中对值设定一个不符合规则的默认值 - * @throws \W7\Validate\Exception\ValidateException + * @throws ValidateException */ public function testBeforeHandlerToVerifySetDefaultValues() { @@ -79,7 +80,7 @@ class TestHandlerFunction extends BaseTestValidate /** * @test 测试在before方法中对值设定一个默认值 - 自定义验证场景 - * @throws \W7\Validate\Exception\ValidateException + * @throws ValidateException */ public function testBeforeHandlerData2() { @@ -96,7 +97,7 @@ class TestHandlerFunction extends BaseTestValidate /** * @test 测试在before方法中对值设定一个不符合规则的默认值 - 自定义验证场景 - * @throws \W7\Validate\Exception\ValidateException + * @throws ValidateException */ public function testBeforeHandlerToVerifySetDefaultValues2() { diff --git a/tests/Test/TestRuleManagerGet.php b/tests/Test/TestRuleManagerGet.php new file mode 100644 index 0000000..3645c0f --- /dev/null +++ b/tests/Test/TestRuleManagerGet.php @@ -0,0 +1,62 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\UserRulesManager; + +class TestRuleManagerGet extends BaseTestValidate +{ + public function testGetStaticMethodForGetAll() + { + $userRules = new UserRulesManager(); + $ref = new \ReflectionClass($userRules); + $_rule = $ref->getProperty('rule'); + $_rule->setAccessible(true); + $_rule = $_rule->getValue($userRules); + + $_message = $ref->getProperty('message'); + $_message->setAccessible(true); + $_message = $_message->getValue($userRules); + + $_customAttributes = $ref->getProperty('customAttributes'); + $_customAttributes->setAccessible(true); + $_customAttributes = $_customAttributes->getValue($userRules); + + list($rule, $message, $customAttributes) = UserRulesManager::get(); + + $this->assertEquals($_rule, $rule); + $this->assertEquals($_message, $message); + $this->assertEquals($_customAttributes, $customAttributes); + } + + public function testGetStaticMethodForGetOnly() + { + $fields = ['user', 'pass']; + list($rule, $message, $customAttributes) = UserRulesManager::get($fields); + $this->assertCount(2, $rule); + $this->assertCount(2, $customAttributes); + + $this->assertEquals('用户名必须为邮箱', $message['user.email']); + $this->assertEquals('密码长度错误', $message['pass.lengthBetween']); + } + + public function testGetMethodForScene() + { + $userRules = new UserRulesManager(); + + $this->assertCount(2, $userRules->scene('login')->getRules()); + $this->assertCount(2, $userRules->login()[0]); + $this->assertCount(2, $userRules::login()[0]); + } +} diff --git a/tests/Test/TestRuleManagerScene.php b/tests/Test/TestRuleManagerScene.php new file mode 100644 index 0000000..d21cab4 --- /dev/null +++ b/tests/Test/TestRuleManagerScene.php @@ -0,0 +1,86 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\Rules\Length; +use W7\Tests\Material\UserRulesManager; + +class TestRuleManagerScene extends BaseTestValidate +{ + public function testGetAllRule() + { + $this->assertCount(5, (new UserRulesManager())->getRules()); + } + + public function testSceneIsLogin() + { + $userRule = new UserRulesManager(); + + $needRules = [ + 'user' => 'required|email', + 'pass' => 'required|lengthBetween:6,16' + ]; + + $this->assertEquals($needRules, $userRule->scene('login')->getRules()); + $this->assertEquals($needRules, $userRule->getRules(null, 'login')); + $this->assertEquals($needRules, $userRule->getInitialRules('login')); + } + + public function testCustomValidateScene() + { + $userRule = new UserRulesManager(); + $rules = $userRule->scene('register')->getRules(); + + $this->assertCount(4, $rules); + $this->assertArrayHasKey('remark', $rules); + $this->assertFalse(in_array('alpha_dash', $rules['remark'])); + $this->assertTrue(in_array('chs', $rules['remark'])); + + $rules = $userRule->scene('registerNeedCaptcha')->getRules(); + $this->assertCount(5, $rules); + $this->assertArrayHasKey('captcha', $rules); + } + + public function testExtendsRule() + { + $userRule = new UserRulesManager(); + + $rules = $userRule->scene('captcha')->getCheckRules(); + + $this->assertArrayHasKey('captcha', $rules); + $haveRequiredRule = $haveCustomRule = $haveExtendRule = $extendRuleName = false; + foreach ($rules['captcha'] as $rule) { + switch ($rule) { + case 'required': + $haveRequiredRule = true; + break; + case $rule instanceof Length: + $haveCustomRule = true; + break; + case 32 === strlen($rule): + $haveExtendRule = true; + $extendRuleName = $rule; + break; + } + } + + $this->assertTrue($haveRequiredRule); + $this->assertTrue($haveCustomRule); + $this->assertTrue($haveExtendRule); + + $messages = $userRule->getMessages(); + + $this->assertEquals('验证码错误', $messages['captcha.' . $extendRuleName]); + } +} diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index 707a8d8..1023180 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -14,47 +14,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\ArticleValidate; use W7\Tests\Material\BaseTestValidate; -use W7\Tests\Material\Rules\Length; use W7\Validate\Exception\ValidateException; -use W7\Validate\RuleManager; -use W7\Validate\Support\Concerns\SceneInterface; - -class UserRules extends RuleManager -{ - protected $rule = [ - 'user' => 'required|email', - 'pass' => 'required|lengthBetween:6,16', - 'name' => 'required|chs|lengthBetween:2,4', - 'remark' => 'required|alpha_dash', - 'captcha' => 'required|length:4|checkCaptcha', - ]; - - protected $scene = [ - 'login' => ['user', 'pass'], - 'captcha' => ['captcha'] - ]; - - protected $message = [ - 'captcha.checkCaptcha' => '验证码错误' - ]; - - protected function sceneRegister(SceneInterface $scene) - { - return $scene->only(['user', 'pass', 'name', 'remark']) - ->remove('remark', 'required|alpha_dash') - ->append('remark', 'chs'); - } - - protected function sceneRegisterNeedCaptcha(SceneInterface $scene) - { - return $this->sceneRegister($scene)->appendCheckField('captcha'); - } - - public function ruleCheckCaptcha($att, $value): bool - { - return true; - } -} class TestValidateScene extends BaseTestValidate { @@ -69,71 +29,6 @@ class TestValidateScene extends BaseTestValidate ]; } - public function testGetAllRule() - { - $this->assertCount(5, (new UserRules())->getRules()); - } - - public function testSceneIsLogin() - { - $userRule = new UserRules(); - - $needRules = [ - 'user' => 'required|email', - 'pass' => 'required|lengthBetween:6,16' - ]; - - $this->assertEquals($needRules, $userRule->scene('login')->getRules()); - $this->assertEquals($needRules, $userRule->getRules('login')); - } - - public function testCustomValidateScene() - { - $userRule = new UserRules(); - $rules = $userRule->scene('register')->getRules(); - - $this->assertCount(4, $rules); - $this->assertArrayHasKey('remark', $rules); - $this->assertFalse(in_array('alpha_dash', $rules['remark'])); - $this->assertTrue(in_array('chs', $rules['remark'])); - - $rules = $userRule->scene('registerNeedCaptcha')->getRules(); - $this->assertCount(5, $rules); - $this->assertArrayHasKey('captcha', $rules); - } - - public function testExtendsRule() - { - $userRule = new UserRules(); - - $rules = $userRule->scene('captcha')->getCheckRules(); - - $this->assertArrayHasKey('captcha', $rules); - $haveRequiredRule = $haveCustomRule = $haveExtendRule = $extendRuleName = false; - foreach ($rules['captcha'] as $rule) { - switch ($rule) { - case 'required': - $haveRequiredRule = true; - break; - case $rule instanceof Length: - $haveCustomRule = true; - break; - case 32 === strlen($rule): - $haveExtendRule = true; - $extendRuleName = $rule; - break; - } - } - - $this->assertTrue($haveRequiredRule); - $this->assertTrue($haveCustomRule); - $this->assertTrue($haveExtendRule); - - $messages = $userRule->getMessages(); - - $this->assertEquals('验证码错误', $messages['captcha.' . $extendRuleName]); - } - /** * @test 测试没有指定验证场景的情况 * @throws ValidateException -- Gitee From 7a1f7d271407d204c7c82f9bdab17a514d3a0783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 18 May 2021 19:24:15 +0800 Subject: [PATCH 078/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E8=A7=84?= =?UTF-8?q?=E5=88=99=E7=AE=A1=E7=90=86=E5=99=A8=E7=9A=84get=E6=96=B9?= =?UTF-8?q?=E6=B3=95$initial=E5=8F=82=E6=95=B0=E9=BB=98=E8=AE=A4=E4=B8=BAf?= =?UTF-8?q?alse=20[A]=20=E5=A2=9E=E5=8A=A0=E9=9D=99=E6=80=81=E6=96=B9?= =?UTF-8?q?=E6=B3=95getBySceneName?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 14 ++++---------- tests/Test/TestRuleManagerGet.php | 5 ++--- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index 752e533..9fc5f0b 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -547,10 +547,10 @@ class RuleManager * Note: This method is not affected by the validate {@see scene} * * @param null|string|array $fields Field name or array of fields, or if null, return all - * @param bool $initial Whether to get the original rule, default is true + * @param bool $initial Whether to get the original rule, default is false * @return array Returns three arrays of rules, error messages, and custom attribute */ - public static function get($fields = null, bool $initial = true): array + public static function get($fields = null, bool $initial = false): array { $validate = new static(); $rules = $validate->getRules($fields); @@ -568,10 +568,10 @@ class RuleManager * Get rules, error messages and custom attribute by scene name * * @param string $sceneName - * @param bool $initial Whether to get the original rule, default is true + * @param bool $initial Whether to get the original rule, default is false * @return array */ - protected static function getBySceneName(string $sceneName, bool $initial = true): array + public static function getBySceneName(string $sceneName, bool $initial = false): array { $validate = new static(); $rules = $validate->getInitialRules($sceneName); @@ -584,12 +584,6 @@ class RuleManager return [$rules, $message, $customAttributes]; } - public function __call($name, $arguments) - { - $initial = !(count($arguments) > 0 && false === $arguments[0]); - return $this->getBySceneName($name, $initial); - } - public static function __callStatic($name, $arguments) { $initial = !(count($arguments) > 0 && false === $arguments[0]); diff --git a/tests/Test/TestRuleManagerGet.php b/tests/Test/TestRuleManagerGet.php index 3645c0f..cd4a841 100644 --- a/tests/Test/TestRuleManagerGet.php +++ b/tests/Test/TestRuleManagerGet.php @@ -33,7 +33,7 @@ class TestRuleManagerGet extends BaseTestValidate $_customAttributes->setAccessible(true); $_customAttributes = $_customAttributes->getValue($userRules); - list($rule, $message, $customAttributes) = UserRulesManager::get(); + list($rule, $message, $customAttributes) = UserRulesManager::get(null, true); $this->assertEquals($_rule, $rule); $this->assertEquals($_message, $message); @@ -43,7 +43,7 @@ class TestRuleManagerGet extends BaseTestValidate public function testGetStaticMethodForGetOnly() { $fields = ['user', 'pass']; - list($rule, $message, $customAttributes) = UserRulesManager::get($fields); + list($rule, $message, $customAttributes) = UserRulesManager::get($fields, true); $this->assertCount(2, $rule); $this->assertCount(2, $customAttributes); @@ -56,7 +56,6 @@ class TestRuleManagerGet extends BaseTestValidate $userRules = new UserRulesManager(); $this->assertCount(2, $userRules->scene('login')->getRules()); - $this->assertCount(2, $userRules->login()[0]); $this->assertCount(2, $userRules::login()[0]); } } -- Gitee From 9be5b92b1a6ea72936cebbf48e0f999287fbcc5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 19 May 2021 15:04:40 +0800 Subject: [PATCH 079/152] =?UTF-8?q?[U]=20=E5=B0=86ValidateConfig=E4=B8=AD?= =?UTF-8?q?=E5=85=B3=E4=BA=8E=E4=B8=AD=E9=97=B4=E4=BB=B6=E7=9A=84=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E6=94=BE=E5=88=B0ValidateMiddlewareConfig=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Concerns/ValidateFactoryInterface.php | 27 +++ .../Middleware/Laravel/ValidateMiddleware.php | 4 +- .../Middleware/Rangine/ValidateMiddleware.php | 4 +- src/Support/Storage/ValidateConfig.php | 100 ----------- src/Support/Storage/ValidateFactory.php | 9 +- .../Storage/ValidateMiddlewareConfig.php | 166 ++++++++++++++++++ 6 files changed, 202 insertions(+), 108 deletions(-) create mode 100644 src/Support/Concerns/ValidateFactoryInterface.php create mode 100644 src/Support/Storage/ValidateMiddlewareConfig.php diff --git a/src/Support/Concerns/ValidateFactoryInterface.php b/src/Support/Concerns/ValidateFactoryInterface.php new file mode 100644 index 0000000..a34e031 --- /dev/null +++ b/src/Support/Concerns/ValidateFactoryInterface.php @@ -0,0 +1,27 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Concerns; + +use W7\Validate\Validate; + +interface ValidateFactoryInterface +{ + /** + * Get validator based on controller + * + * @param string $controller + * @param string $scene + * @return false|Validate + */ + public function getValidate(string $controller, string $scene = ''); +} diff --git a/src/Support/Middleware/Laravel/ValidateMiddleware.php b/src/Support/Middleware/Laravel/ValidateMiddleware.php index 2ba43b4..28b3562 100644 --- a/src/Support/Middleware/Laravel/ValidateMiddleware.php +++ b/src/Support/Middleware/Laravel/ValidateMiddleware.php @@ -14,7 +14,7 @@ namespace W7\Validate\Support\Middleware\Laravel; use Closure; use Illuminate\Http\Request; -use W7\Validate\Support\Storage\ValidateFactory; +use W7\Validate\Support\Storage\ValidateMiddlewareConfig; class ValidateMiddleware { @@ -22,7 +22,7 @@ class ValidateMiddleware { list($controller, $scene) = explode('@', $request->route()->getActionName()); - $validator = ValidateFactory::getValidate($controller, $scene); + $validator = ValidateMiddlewareConfig::instance()->getValidateFactory()->getValidate($controller, $scene); if ($validator) { $data = $validator->check($request->all()); diff --git a/src/Support/Middleware/Rangine/ValidateMiddleware.php b/src/Support/Middleware/Rangine/ValidateMiddleware.php index aa3912c..921bb0b 100644 --- a/src/Support/Middleware/Rangine/ValidateMiddleware.php +++ b/src/Support/Middleware/Rangine/ValidateMiddleware.php @@ -19,7 +19,7 @@ use W7\Core\Route\Route; use W7\Facade\Context; use W7\Core\Middleware\MiddlewareAbstract; use W7\Http\Message\Server\Request; -use W7\Validate\Support\Storage\ValidateFactory; +use W7\Validate\Support\Storage\ValidateMiddlewareConfig; class ValidateMiddleware extends MiddlewareAbstract { @@ -35,7 +35,7 @@ class ValidateMiddleware extends MiddlewareAbstract list($controller, $scene) = $routeHandler; - $validator = ValidateFactory::getValidate($controller, $scene); + $validator = ValidateMiddlewareConfig::instance()->getValidateFactory()->getValidate($controller, $scene); if ($validator) { $data = array_merge([], $request->getQueryParams(), $request->getParsedBody(), $request->getUploadedFiles()); diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 8202425..770d4cd 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -31,12 +31,6 @@ final class ValidateConfig */ protected $rulesPath = []; - /** - * Automatic loading of validator rules - * @var array - */ - protected $autoValidatePath = []; - /** * Translator * @var Translator @@ -68,12 +62,6 @@ final class ValidateConfig */ protected $framework = 0; - /** - * Validator specific association - * @var array - */ - protected $validateLink = []; - protected static $instance; public static function instance(): ValidateConfig @@ -217,84 +205,6 @@ final class ValidateConfig return $this->translator; } - /** - * Set up auto-load validator rules - * - * @param string $controllerPath Controller path - * @param string $validatePath Validator path - * @return $this - */ - public function setAutoValidatePath(string $controllerPath, string $validatePath): ValidateConfig - { - if ('\\' !== substr($controllerPath, -1)) { - $controllerPath = $controllerPath . '\\'; - } - - if ('\\' !== substr($validatePath, -1)) { - $validatePath = $validatePath . '\\'; - } - - $this->autoValidatePath[$controllerPath] = $validatePath; - return $this; - } - - /** - * Set Validator Association - * - * @param string|string[] $controller Controller namespace - * To specify a method, pass an array with the second element being the method name - * @param string|string[] $validate Validator namespace - * To specify a scene, pass an array with the second element being the scene name - * @return $this - */ - public function setValidateLink($controller, $validate): ValidateConfig - { - if (is_array($controller)) { - $controllers = $controller; - $controller = $controllers[0]; - $method = $controllers[1]; - # The "\" symbol must not be present in the array - $controller = md5($controller); - if (count($controllers) >= 2) { - if (isset($this->validateLink[$controller])) { - $_validate = $this->validateLink[$controller]; - $_validate = array_merge($_validate, [ - $method => $validate - ]); - $this->validateLink[$controller] = $_validate; - } else { - $this->validateLink[$controller] = [ - $method => $validate - ]; - } - } - } else { - $controller = md5($controller); - if (isset($this->validateLink[$controller])) { - $this->validateLink[$controller]['!__other__'] = $validate; - } else { - $this->validateLink[$controller] = [ - '!__other__' => $validate - ]; - } - } - return $this; - } - - /** - * Get validator specific associations - * - * @param string|null $controller Validator full namespace - * @return array - */ - public function getValidateLink(?string $controller = null): array - { - if (null === $controller) { - return $this->validateLink; - } - return $this->validateLink[md5($controller)] ?? []; - } - /** * Set the custom rules namespace prefix, If more than one exists, they all take effect * @@ -317,14 +227,4 @@ final class ValidateConfig { return $this->rulesPath; } - - /** - * Get auto-load validator rules - * - * @return array - */ - public function getAutoValidatePath(): array - { - return $this->autoValidatePath; - } } diff --git a/src/Support/Storage/ValidateFactory.php b/src/Support/Storage/ValidateFactory.php index 920c182..d3981a3 100644 --- a/src/Support/Storage/ValidateFactory.php +++ b/src/Support/Storage/ValidateFactory.php @@ -13,16 +13,17 @@ namespace W7\Validate\Support\Storage; use Exception; +use W7\Validate\Support\Concerns\ValidateFactoryInterface; use W7\Validate\Validate; -class ValidateFactory +class ValidateFactory implements ValidateFactoryInterface { - public static function getValidate(string $controller, string $scene = '') + public function getValidate(string $controller, string $scene = '') { $haveLink = false; $validate = ''; - $validateLink = ValidateConfig::instance()->getValidateLink($controller); + $validateLink = ValidateMiddlewareConfig::instance()->getValidateLink($controller); if (!empty($validateLink)) { # Specified validator for the specified controller method if (isset($validateLink[$scene]) || isset($validateLink['!__other__'])) { @@ -50,7 +51,7 @@ class ValidateFactory # Handles controllers with specified paths $controllerPath = ''; $validatePath = ''; - foreach (ValidateConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { + foreach (ValidateMiddlewareConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { if (false !== strpos($controller, $_controllerPath)) { $controllerPath = $_controllerPath; $validatePath = $_validatePath; diff --git a/src/Support/Storage/ValidateMiddlewareConfig.php b/src/Support/Storage/ValidateMiddlewareConfig.php new file mode 100644 index 0000000..4bfbf8f --- /dev/null +++ b/src/Support/Storage/ValidateMiddlewareConfig.php @@ -0,0 +1,166 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Storage; + +use W7\Validate\Support\Concerns\ValidateFactoryInterface; + +class ValidateMiddlewareConfig +{ + /** + * Automatic loading of validator rules + * @var array + */ + protected $autoValidatePath = []; + + /** + * Validator specific association + * @var array + */ + protected $validateLink = []; + + /** + * Validate Factory + * @var ValidateFactoryInterface + */ + protected $validateFactory; + + /** + * Stored single instance objects + * @var ValidateMiddlewareConfig + */ + protected static $instance; + + public static function instance(): ValidateMiddlewareConfig + { + if (empty(self::$instance)) { + self::$instance = new static(); + } + + return self::$instance; + } + + public function __construct() + { + $this->validateFactory = new ValidateFactory(); + } + + /** + * Set up auto-load validator rules + * + * @param string $controllerPath Controller path + * @param string $validatePath Validator path + * @return $this + */ + public function setAutoValidatePath(string $controllerPath, string $validatePath): ValidateMiddlewareConfig + { + if ('\\' !== substr($controllerPath, -1)) { + $controllerPath = $controllerPath . '\\'; + } + + if ('\\' !== substr($validatePath, -1)) { + $validatePath = $validatePath . '\\'; + } + + $this->autoValidatePath[$controllerPath] = $validatePath; + return $this; + } + + /** + * Set Validator Association + * + * @param string|string[] $controller Controller namespace + * To specify a method, pass an array with the second element being the method name + * @param string|string[] $validate Validator namespace + * To specify a scene, pass an array with the second element being the scene name + * @return $this + */ + public function setValidateLink($controller, $validate): ValidateMiddlewareConfig + { + if (is_array($controller)) { + $controllers = $controller; + $controller = $controllers[0]; + $method = $controllers[1]; + # The "\" symbol must not be present in the array + $controller = md5($controller); + if (count($controllers) >= 2) { + if (isset($this->validateLink[$controller])) { + $_validate = $this->validateLink[$controller]; + $_validate = array_merge($_validate, [ + $method => $validate + ]); + $this->validateLink[$controller] = $_validate; + } else { + $this->validateLink[$controller] = [ + $method => $validate + ]; + } + } + } else { + $controller = md5($controller); + if (isset($this->validateLink[$controller])) { + $this->validateLink[$controller]['!__other__'] = $validate; + } else { + $this->validateLink[$controller] = [ + '!__other__' => $validate + ]; + } + } + return $this; + } + + /** + * Get validator specific associations + * + * @param string|null $controller Validator full namespace + * @return array + */ + public function getValidateLink(?string $controller = null): array + { + if (null === $controller) { + return $this->validateLink; + } + return $this->validateLink[md5($controller)] ?? []; + } + + /** + * Get auto-load validator rules + * + * @return array + */ + public function getAutoValidatePath(): array + { + return $this->autoValidatePath; + } + + /** + * Provide a validate factory + * + * @param ValidateFactoryInterface $validateFactory + * @return $this + */ + public function setValidateFactory(ValidateFactoryInterface $validateFactory): ValidateMiddlewareConfig + { + $this->validateFactory = $validateFactory; + return $this; + } + + /** + * Get a validate factory + * + * @return ValidateFactoryInterface + */ + public function getValidateFactory(): ValidateFactoryInterface + { + return $this->validateFactory; + } +} -- Gitee From 217d7c86a84c294cf97585b3287444593cc6c034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 19 May 2021 17:04:10 +0800 Subject: [PATCH 080/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=99=A8=E4=B8=AD=E9=97=B4=E4=BB=B6=E7=89=B9=E5=AE=9A?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E4=B8=8B=E6=97=A0=E6=B3=95=E6=89=BE=E5=88=B0?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E5=99=A8=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .php-cs-fixer.php | 56 ++++++++++++++++++++++ .php_cs | 62 ------------------------- src/Support/Storage/ValidateFactory.php | 3 +- 3 files changed, 58 insertions(+), 63 deletions(-) create mode 100644 .php-cs-fixer.php delete mode 100644 .php_cs diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php new file mode 100644 index 0000000..4ac4d5a --- /dev/null +++ b/.php-cs-fixer.php @@ -0,0 +1,56 @@ +files() + ->name('*.php') + ->exclude('vendor') + ->in(__DIR__) + ->ignoreDotFiles(true) + ->ignoreVCS(true); + +$fixers = [ + '@PSR2' => true, + 'single_quote' => true, //简单字符串应该使用单引号代替双引号; + 'no_unused_imports' => true, //删除没用到的use + 'no_singleline_whitespace_before_semicolons' => true, //禁止只有单行空格和分号的写法; + 'no_empty_statement' => true, //多余的分号 + 'no_extra_blank_lines' => true, //多余空白行 + 'no_blank_lines_after_phpdoc' => true, //注释和代码中间不能有空行 + 'no_empty_phpdoc' => true, //禁止空注释 + 'phpdoc_indent' => true, //注释和代码的缩进相同 + 'no_blank_lines_after_class_opening' => true, //类开始标签后不应该有空白行; + 'include' => true, //include 和文件路径之间需要有一个空格,文件路径不需要用括号括起来; + 'no_trailing_comma_in_list_call' => true, //删除 list 语句中多余的逗号; + 'no_leading_namespace_whitespace' => true, //命名空间前面不应该有空格; + 'standardize_not_equals' => true, //使用 <> 代替 !=; + 'blank_line_after_opening_tag' => true, //PHP开始标记后换行 + 'indentation_type' => true, + 'concat_space' => [ + 'spacing' => 'one', + ], + 'space_after_semicolon' => [ + 'remove_in_empty_for_expressions' => true, + ], + 'header_comment' => [ + 'comment_type' => 'PHPDoc', + 'header' => "WeEngine System \r\n\r\n(c) We7Team 2021 \r\n\r\nThis is not a free software \r\nUsing it under the license terms\r\nvisited https://www.w7.cc for more details", + ], + 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], //等号对齐、数字箭头符号对齐 + 'whitespace_after_comma_in_array' => true, + 'array_syntax' => ['syntax' => 'short'], + 'ternary_operator_spaces' => true, + 'yoda_style' => true, + 'normalize_index_brace' => true, + 'short_scalar_cast' => true, + 'function_typehint_space' => true, + 'function_declaration' => true, + 'return_type_declaration' => true + +]; +$config = new \PhpCsFixer\Config(); +return $config + ->setRules($fixers) + ->setFinder($finder) + ->setUsingCache(false); diff --git a/.php_cs b/.php_cs deleted file mode 100644 index 7fe86d5..0000000 --- a/.php_cs +++ /dev/null @@ -1,62 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -define('SOFT_NAME', 'WeEngine System'); - -$finder = PhpCsFixer\Finder::create() - ->files() - ->name('*.php') - ->exclude('vendor') - ->in(__DIR__) - ->ignoreDotFiles(true) - ->ignoreVCS(true); - -$fixers = [ - '@PSR2' => true, - 'single_quote' => true, //简单字符串应该使用单引号代替双引号; - 'no_unused_imports' => true, //删除没用到的use - 'no_singleline_whitespace_before_semicolons' => true, //禁止只有单行空格和分号的写法; - 'no_empty_statement' => true, //多余的分号 - 'no_extra_consecutive_blank_lines' => true, //多余空白行 - 'no_blank_lines_after_class_opening' => true, //类开始标签后不应该有空白行; - 'include' => true, //include 和文件路径之间需要有一个空格,文件路径不需要用括号括起来; - 'no_trailing_comma_in_list_call' => true, //删除 list 语句中多余的逗号; - 'no_leading_namespace_whitespace' => true, //命名空间前面不应该有空格; - 'standardize_not_equals' => true, //使用 <> 代替 !=; - 'blank_line_after_opening_tag' => true, //PHP开始标记后换行 - 'indentation_type' => true, - 'concat_space' => [ - 'spacing' => 'one', - ], - 'space_after_semicolon' => [ - 'remove_in_empty_for_expressions' => true, - ], - 'header_comment' => [ - 'comment_type' => 'PHPDoc', - 'header' => SOFT_NAME . " \r\n\r\n(c) We7Team 2021 \r\n\r\nThis is not a free software \r\nUsing it under the license terms\r\nvisited https://www.w7.cc for more details", - ], - 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], //等号对齐、数字箭头符号对齐 - 'whitespace_after_comma_in_array' => true, - 'array_syntax' => ['syntax' => 'short'], - 'ternary_operator_spaces' => true, - 'yoda_style' => true, - 'normalize_index_brace' => true, - 'short_scalar_cast' => true, - 'function_typehint_space' => true, - 'function_declaration' => true, - 'return_type_declaration' => true - -]; -return PhpCsFixer\Config::create() - ->setRules($fixers) - ->setFinder($finder) - ->setUsingCache(false); \ No newline at end of file diff --git a/src/Support/Storage/ValidateFactory.php b/src/Support/Storage/ValidateFactory.php index d3981a3..ec008f3 100644 --- a/src/Support/Storage/ValidateFactory.php +++ b/src/Support/Storage/ValidateFactory.php @@ -65,7 +65,8 @@ class ValidateFactory implements ValidateFactoryInterface $validate = str_replace($controllerPath, '', $controller); $_namespace = explode('\\', $validate); $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); - $validate = $validatePath . (!empty($_namespace) ? implode('\\', $_namespace) . '\\' : '') . $fileName; + $_namespace = implode('\\', $_namespace); + $validate = $validatePath . $_namespace . (!empty($_namespace) ? '\\' : '') . $fileName; } if (class_exists($validate)) { -- Gitee From a177f8d7100cc1f5272f5942e2c57ff22b61d2e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 19 May 2021 20:41:10 +0800 Subject: [PATCH 081/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9getRules?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E5=88=A0=E9=99=A4=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=8F=82=E6=95=B0=EF=BC=8C=E5=8F=AF=E7=94=A8?= =?UTF-8?q?scene=E6=96=B9=E6=B3=95=E6=9B=BF=E4=BB=A3=EF=BC=8C=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0$initial=E5=8F=82=E6=95=B0=E7=94=A8=E4=BA=8E=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=8E=9F=E5=A7=8B=E8=A7=84=E5=88=99=E3=80=82=20[U]=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=9D=99=E6=80=81=E6=96=B9=E6=B3=95=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E8=8E=B7=E5=8F=96=E8=A7=84=E5=88=99=E4=B8=BA=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E5=90=8E=E7=9A=84=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index 9fc5f0b..0129769 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -403,20 +403,23 @@ class RuleManager /** * Get the specified rule * - * @param string|string[]|null $field Field name or array of field names.If $field is null, then return all rules - * If a scene value is set, the specified rule is retrieved from the current scene. + * @param string|string[]|null $field Field name or array of field names.If $field is null, then return all rules + * If a scene value is set, the specified rule is retrieved from the current scene. * - * @param string $sceneName Scene name, If this value is not provided, the current scene will be the default. - * If you want to ignore the scene, please provide the value null + * @param bool $initial Whether to get the original rule, default is false * @return array */ - public function getRules($field = null, string $sceneName = ''): array + public function getRules($field = null, bool $initial = false): array { - $rules = $this->getInitialRules($sceneName); + $rules = $this->getInitialRules(); if (null === $field) { return $rules; } + if (false === $initial) { + $rules = $this->getCheckRules($rules); + } + $field = is_array($field) ? $field : [$field]; return array_intersect_key($rules, array_flip($field)); } @@ -586,7 +589,7 @@ class RuleManager public static function __callStatic($name, $arguments) { - $initial = !(count($arguments) > 0 && false === $arguments[0]); + $initial = (count($arguments) > 0 && true === $arguments[0]); return self::getBySceneName($name, $initial); } } -- Gitee From 4c3e096f7fd010849100ff19379986e8268151b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 20 May 2021 10:29:22 +0800 Subject: [PATCH 082/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DGetRules?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=85=A8=E9=83=A8=E8=A7=84=E5=88=99=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E5=80=99=E4=B8=8D=E4=BC=9A=E8=A7=A3=E6=9E=90=E8=A7=84?= =?UTF-8?q?=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index 0129769..734d04b 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -412,16 +412,16 @@ class RuleManager public function getRules($field = null, bool $initial = false): array { $rules = $this->getInitialRules(); - if (null === $field) { - return $rules; + if (null !== $field) { + $field = is_array($field) ? $field : [$field]; + $rules = array_intersect_key($rules, array_flip($field)); } if (false === $initial) { $rules = $this->getCheckRules($rules); } - $field = is_array($field) ? $field : [$field]; - return array_intersect_key($rules, array_flip($field)); + return $rules; } /** @@ -589,7 +589,7 @@ class RuleManager public static function __callStatic($name, $arguments) { - $initial = (count($arguments) > 0 && true === $arguments[0]); + $initial = count($arguments) > 0 ? $arguments[0] : false; return self::getBySceneName($name, $initial); } } -- Gitee From 575fcddf8e226bc9cb8a50c9d825d36b31939bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 20 May 2021 10:32:02 +0800 Subject: [PATCH 083/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DGet=E9=9D=99?= =?UTF-8?q?=E6=80=81=E6=96=B9=E6=B3=95=E8=8E=B7=E5=8F=96=E5=8E=9F=E5=A7=8B?= =?UTF-8?q?=E8=A7=84=E5=88=99=E9=94=99=E8=AF=AF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index 734d04b..3c4e096 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -556,14 +556,10 @@ class RuleManager public static function get($fields = null, bool $initial = false): array { $validate = new static(); - $rules = $validate->getRules($fields); + $rules = $validate->getRules($fields, $initial); $message = $validate->getMessages($fields, null, true); $customAttributes = $validate->getCustomAttributes($fields); - - if (!$initial) { - $rules = $validate->getCheckRules($rules); - } - + return [$rules, $message, $customAttributes]; } -- Gitee From d5c3be05ce675c5a74a5b0e0061ac065962371ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 20 May 2021 10:34:09 +0800 Subject: [PATCH 084/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Test/TestRuleManagerScene.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Test/TestRuleManagerScene.php b/tests/Test/TestRuleManagerScene.php index d21cab4..fde857d 100644 --- a/tests/Test/TestRuleManagerScene.php +++ b/tests/Test/TestRuleManagerScene.php @@ -32,7 +32,7 @@ class TestRuleManagerScene extends BaseTestValidate 'pass' => 'required|lengthBetween:6,16' ]; - $this->assertEquals($needRules, $userRule->scene('login')->getRules()); + $this->assertEquals($needRules, $userRule->scene('login')->getRules(null,true)); $this->assertEquals($needRules, $userRule->getRules(null, 'login')); $this->assertEquals($needRules, $userRule->getInitialRules('login')); } @@ -40,7 +40,7 @@ class TestRuleManagerScene extends BaseTestValidate public function testCustomValidateScene() { $userRule = new UserRulesManager(); - $rules = $userRule->scene('register')->getRules(); + $rules = $userRule->scene('register')->getRules(null,true); $this->assertCount(4, $rules); $this->assertArrayHasKey('remark', $rules); -- Gitee From e5e8c6cf738c0fb1d45fdef723732517003cb195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 20 May 2021 19:22:09 +0800 Subject: [PATCH 085/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E4=B8=ADhandler=E6=96=B9=E6=B3=95=E4=B8=BAevent=20[U]?= =?UTF-8?q?=20=E4=BF=AE=E6=94=B9=E9=AA=8C=E8=AF=81=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=8F=AA=E8=83=BD=E5=A4=84=E7=90=86=E9=AA=8C=E8=AF=81=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E6=94=AF=E6=8C=81=E5=A4=84=E7=90=86=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- src/Support/Event/ValidateEventAbstract.php | 38 +++--- src/Support/Event/ValidateEventInterface.php | 15 +-- src/Support/Storage/ValidateHandler.php | 74 ---------- src/Support/ValidateScene.php | 8 +- src/Validate.php | 135 +++++++++---------- tests/Material/Event/CheckIsChs.php | 24 ++++ tests/Material/Event/Increasing.php | 32 ----- tests/Material/Event/SetDefault.php | 32 ----- tests/Material/TestValidate.php | 43 ++++++ tests/Test/TestHandlerEvent.php | 29 ++++ 11 files changed, 184 insertions(+), 248 deletions(-) delete mode 100644 src/Support/Storage/ValidateHandler.php create mode 100644 tests/Material/Event/CheckIsChs.php delete mode 100644 tests/Material/Event/Increasing.php delete mode 100644 tests/Material/Event/SetDefault.php create mode 100644 tests/Material/TestValidate.php diff --git a/composer.json b/composer.json index d6b4189..0b17fc3 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^7.2.5|^8.0", - "illuminate/validation": "^6.0|^7.0" + "illuminate/validation": "^6.0|^7.0|^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2.18", diff --git a/src/Support/Event/ValidateEventAbstract.php b/src/Support/Event/ValidateEventAbstract.php index 8619511..2dd99bb 100644 --- a/src/Support/Event/ValidateEventAbstract.php +++ b/src/Support/Event/ValidateEventAbstract.php @@ -12,37 +12,35 @@ namespace W7\Validate\Support\Event; -use Closure; - abstract class ValidateEventAbstract implements ValidateEventInterface { /** - * Current validation scenarios + * Current validation scene name * @var ?string */ - protected $sceneName; + public $sceneName; - /** @inheritDoc */ - public function beforeValidate(array $data, Closure $next) - { - return $next($data); - } + /** + * Current validated data + * @var array + */ + public $data; + + /** + * Error message + * @var string + */ + public $message; /** @inheritDoc */ - public function afterValidate(array $data, Closure $next) + public function beforeValidate(): bool { - return $next($data); + return true; } - /** - * Write the name of the current validation scenario - * - * @param string|null $sceneName - * @return $this - */ - final public function setSceneName(?string $sceneName): ValidateEventAbstract + /** @inheritDoc */ + public function afterValidate(): bool { - $this->sceneName = $sceneName; - return $this; + return true; } } diff --git a/src/Support/Event/ValidateEventInterface.php b/src/Support/Event/ValidateEventInterface.php index 346f99a..f4bcdd7 100644 --- a/src/Support/Event/ValidateEventInterface.php +++ b/src/Support/Event/ValidateEventInterface.php @@ -12,24 +12,19 @@ namespace W7\Validate\Support\Event; -use Closure; - interface ValidateEventInterface { /** * Methods implemented prior to validation * - * @param array $data - * @param Closure $next - * @return mixed + * @return bool */ - public function beforeValidate(array $data, Closure $next); + public function beforeValidate(): bool; /** * Methods implemented after validation - * @param array $data Validated data - * @param Closure $next - * @return mixed + * + * @return bool */ - public function afterValidate(array $data, Closure $next); + public function afterValidate(): bool; } diff --git a/src/Support/Storage/ValidateHandler.php b/src/Support/Storage/ValidateHandler.php deleted file mode 100644 index eb8850e..0000000 --- a/src/Support/Storage/ValidateHandler.php +++ /dev/null @@ -1,74 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Validate\Support\Storage; - -use Closure; -use W7\Validate\Exception\ValidateException; -use W7\Validate\Support\Event\ValidateEventAbstract; - -class ValidateHandler -{ - protected $handlers = []; - - protected $data = []; - /** - * @var string|null - */ - protected $sceneName = null; - - public function __construct(array $data, array $handlers, string $sceneName = null) - { - $this->data = $data; - $this->handlers = $handlers; - $this->sceneName = $sceneName; - } - - protected function carry(): Closure - { - return function ($stack, $pipe) { - return function ($data) use ($stack, $pipe) { - return $pipe($data, $stack); - }; - }; - } - - protected function pipes(string $method): array - { - return array_map(function ($middleware) use ($method) { - return function ($data, $next) use ($middleware, $method) { - list($callback, $param) = $middleware; - if (class_exists($callback) && is_subclass_of($callback, ValidateEventAbstract::class)) { - /** @var ValidateEventAbstract $handler */ - $handler = new $callback(...$param); - $handler->setSceneName($this->sceneName); - return call_user_func([$handler, $method], $data, $next); - } else { - throw new ValidateException('Event error or nonexistence'); - } - }; - }, $this->handlers); - } - - public function handle(string $method) - { - $pipeline = array_reduce( - array_reverse($this->pipes($method)), - $this->carry(), - function ($data) { - return $data; - } - ); - - return $pipeline($this->data); - } -} diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 4a061c7..75ac8c9 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -21,7 +21,7 @@ use W7\Validate\Support\Storage\ValidateCollection; * Class ValidateScene * @package W7\Validate\Support * - * @property-read array $handlers Events to be processed + * @property-read array $events Events to be processed * @property-read array $afters Methods to be executed after validation * @property-read array $befores Methods to be executed before validation * @property-read bool $eventPriority Event Priority @@ -38,7 +38,7 @@ class ValidateScene extends RuleManagerScene * Events to be processed * @var array */ - protected $handlers = []; + protected $events = []; /** * Methods to be executed after validation @@ -115,9 +115,9 @@ class ValidateScene extends RuleManagerScene * @param mixed ...$params Parameters to be passed to the event * @return $this */ - public function handler(string $handler, ...$params): ValidateScene + public function event(string $handler, ...$params): ValidateScene { - $this->handlers[] = [$handler, $params]; + $this->events[] = [$handler, $params]; return $this; } diff --git a/src/Validate.php b/src/Validate.php index 3b0d4cb..2ac72ad 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -17,9 +17,9 @@ use Illuminate\Validation\ValidationException; use LogicException; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Concerns\MessageProviderInterface; +use W7\Validate\Support\Event\ValidateEventAbstract; use W7\Validate\Support\MessageProvider; use W7\Validate\Support\Storage\ValidateConfig; -use W7\Validate\Support\Storage\ValidateHandler; use W7\Validate\Support\ValidateScene; class Validate extends RuleManager @@ -28,7 +28,7 @@ class Validate extends RuleManager * Global Event Handler * @var array */ - protected $handler = []; + protected $event = []; /** * Whether to stop running after the first verification failure @@ -42,6 +42,10 @@ class Validate extends RuleManager */ protected $filled = true; + protected $filter = []; + + protected $default = []; + /** * Event Priority * @var bool @@ -52,7 +56,7 @@ class Validate extends RuleManager * Validator event handling class * @var array */ - private $handlers = []; + private $events = []; /** * Methods to be executed before validation @@ -116,7 +120,7 @@ class Validate extends RuleManager try { $this->init(); $this->checkData = $data; - $this->addHandler($this->handler); + $this->addEvent($this->event); $rule = $this->getCheckRules($this->getInitialRules()); if ($this->filled) { @@ -128,28 +132,28 @@ class Validate extends RuleManager } if ($this->eventPriority) { - $data = $this->handleEvent($data, 'beforeValidate'); - $data = $this->handleCallback($data, 1); + $this->handleEvent($data, 'beforeValidate'); + $this->handleCallback($data, 1); } else { - $data = $this->handleCallback($data, 1); - $data = $this->handleEvent($data, 'beforeValidate'); + $this->handleCallback($data, 1); + $this->handleEvent($data, 'beforeValidate'); } - $v = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes); - $data = $v->validate(); + $data = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes)->validate(); if ($this->eventPriority) { - $data = $this->handleCallback($data, 2); - $data = $this->handleEvent($data, 'afterValidate'); + $this->handleCallback($data, 2); + $this->handleEvent($data, 'afterValidate'); } else { - $data = $this->handleEvent($data, 'afterValidate'); - $data = $this->handleCallback($data, 2); + $this->handleEvent($data, 'afterValidate'); + $this->handleCallback($data, 2); } return $data; } catch (ValidationException $e) { $errors = $this->getMessageProvider()->handleMessage($e->errors()); $errorMessage = ''; + foreach ($errors as $message) { $errorMessage = $message[0]; break; @@ -179,9 +183,9 @@ class Validate extends RuleManager if (method_exists($this, 'scene' . ucfirst($sceneName))) { $scene = new ValidateScene($this->rule); call_user_func([$this, 'scene' . ucfirst($sceneName)], $scene); - $this->handlers = array_merge($this->handlers, $scene->handlers); - $this->afters = array_merge($this->handlers, $scene->afters); - $this->befores = array_merge($this->handlers, $scene->befores); + $this->event = array_merge($this->event, $scene->events); + $this->afters = array_merge($this->afters, $scene->afters); + $this->befores = array_merge($this->befores, $scene->befores); $this->eventPriority = $scene->eventPriority; return $scene->getRules(); } @@ -190,10 +194,10 @@ class Validate extends RuleManager $sceneRule = $this->scene[$sceneName]; // Determine if an event is defined - if (isset($sceneRule['handler'])) { - $handlers = $sceneRule['handler']; - $this->addHandler($handlers); - unset($sceneRule['handler']); + if (isset($sceneRule['event'])) { + $events = $sceneRule['event']; + $this->addEvent($events); + unset($sceneRule['event']); } // Methods to be executed before determining the presence or absence of authentication @@ -247,10 +251,9 @@ class Validate extends RuleManager * * @param array $data * @param int $type 1 before method 2 after method - * @return array * @throws ValidateException */ - private function handleCallback(array $data, int $type): array + private function handleCallback(array $data, int $type) { switch ($type) { case 1: @@ -266,35 +269,22 @@ class Validate extends RuleManager } if (empty($callbacks)) { - return $data; + return; } - $callback = array_map(function ($callback) use ($typeName) { - return function ($data, $next) use ($callback, $typeName) { - list($callback, $param) = $callback; - $callback = $typeName . ucfirst($callback); - if (method_exists($this, $callback)) { - return call_user_func([$this, $callback], $data, $next, ...$param); - } + foreach ($callbacks as $callback) { + list($callback, $param) = $callback; + $callback = $typeName . ucfirst($callback); + if (!method_exists($this, $callback)) { throw new LogicException('Method Not Found'); - }; - }, $callbacks); - - $pipeline = array_reduce( - array_reverse($callback), - function ($stack, $pipe) { - return function ($data) use ($stack, $pipe) { - return $pipe($data, $stack); - }; - }, - function ($data) { - return $data; } - ); - - $data = $pipeline($data); - - return $this->handleEventResult($data); + if (($result = call_user_func([$this, $callback], $data, ...$param)) !== true) { + if (isset($this->message[$result])) { + $result = $this->getMessageProvider()->handleMessage($this->message[$result]); + } + throw new ValidateException($result, 403); + } + } } /** @@ -302,37 +292,32 @@ class Validate extends RuleManager * * @param array $data Validated data * @param string $method Event Name - * @return array * @throws ValidateException */ - private function handleEvent(array $data, string $method): array + private function handleEvent(array $data, string $method) { - if (empty($this->handlers)) { - return $data; + if (empty($this->events)) { + return; } - $result = (new ValidateHandler($data, $this->handlers, $this->getCurrentSceneName()))->handle($method); - return $this->handleEventResult($result); - } - - /** - * Handling of event results - * - * @param $result - * @return array - * @throws ValidateException - */ - private function handleEventResult($result): array - { - if (is_string($result)) { - if (isset($this->message[$result])) { - $result = $this->getMessageProvider()->handleMessage($this->message[$result]); + + foreach ($this->events as $events) { + list($callback, $param) = $events; + if (class_exists($callback) && is_subclass_of($callback, ValidateEventAbstract::class)) { + /** @var ValidateEventAbstract $handler */ + $handler = new $callback(...$param); + $handler->sceneName = $this->getCurrentSceneName(); + $handler->data = $data; + if (($result = call_user_func([$handler, $method])) !== true) { + $message = $handler->message; + if (isset($this->message[$message])) { + $message = $this->getMessageProvider()->handleMessage($this->message[$message]); + } + throw new ValidateException($message, 403); + } + } else { + throw new ValidateException('Event error or nonexistence'); } - throw new ValidateException($result, 403); - } elseif (is_array($result)) { - return $result; } - - throw new LogicException('Validate event return type error'); } /** @@ -393,7 +378,7 @@ class Validate extends RuleManager * * @param $handlers */ - private function addHandler($handlers) + private function addEvent($handlers) { $this->addCallback(0, $handlers); } @@ -428,7 +413,7 @@ class Validate extends RuleManager { switch ($intType) { case 0: - $type = 'handlers'; + $type = 'events'; break; case 1: $type = 'befores'; diff --git a/tests/Material/Event/CheckIsChs.php b/tests/Material/Event/CheckIsChs.php new file mode 100644 index 0000000..cf77436 --- /dev/null +++ b/tests/Material/Event/CheckIsChs.php @@ -0,0 +1,24 @@ +field = $field; + } + + public function afterValidate(): bool + { + return is_scalar($this->data[$this->field]) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$this->data[$this->field]); + } +} \ No newline at end of file diff --git a/tests/Material/Event/Increasing.php b/tests/Material/Event/Increasing.php deleted file mode 100644 index c7c645f..0000000 --- a/tests/Material/Event/Increasing.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Tests\Material\Event; - -use Closure; -use W7\Validate\Support\Event\ValidateEventAbstract; - -class Increasing extends ValidateEventAbstract -{ - protected $field; - - public function __construct(string $field) - { - $this->field = $field; - } - - public function afterValidate(array $data, Closure $next) - { - $data[$this->field] ++; - return $next($data); - } -} diff --git a/tests/Material/Event/SetDefault.php b/tests/Material/Event/SetDefault.php deleted file mode 100644 index 3eaa796..0000000 --- a/tests/Material/Event/SetDefault.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Tests\Material\Event; - -use Closure; -use W7\Validate\Support\Event\ValidateEventAbstract; - -class SetDefault extends ValidateEventAbstract -{ - protected $default; - - public function __construct(array $default) - { - $this->default = $default; - } - - public function beforeValidate(array $data, Closure $next) - { - $data = array_merge($this->default, $data); - return $next($data); - } -} diff --git a/tests/Material/TestValidate.php b/tests/Material/TestValidate.php new file mode 100644 index 0000000..7f6729b --- /dev/null +++ b/tests/Material/TestValidate.php @@ -0,0 +1,43 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material; + +use W7\Tests\Material\Event\CheckIsChs; +use W7\Validate\Validate; + +class TestValidate extends Validate +{ + protected $rule = [ + 'name' => 'required' + ]; + + protected $scene = [ + 'errorEvent' => ['name', 'event' => [CheckIsChs::class => ['name']]], + 'checkName' => ['name', 'after' => ['checkNameIsAdmin' => 'name']], + 'beforeThrowError' => ['before' => 'throwError'] + ]; + + protected function afterCheckNameIsAdmin($data, $field) + { + if (($data[$field] ?? '') === 'admin') { + return true; + } + + return '用户名不是admin'; + } + + protected function beforeThrowError($data) + { + return 'error'; + } +} diff --git a/tests/Test/TestHandlerEvent.php b/tests/Test/TestHandlerEvent.php index e78a915..81448cc 100644 --- a/tests/Test/TestHandlerEvent.php +++ b/tests/Test/TestHandlerEvent.php @@ -14,10 +14,39 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; use W7\Tests\Material\HandlerEventValidate; +use W7\Tests\Material\TestValidate; use W7\Validate\Exception\ValidateException; class TestHandlerEvent extends BaseTestValidate { + public function testErrorEvent() + { + $v = new TestValidate(); + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('不是中文'); + $v->scene('errorEvent')->check([ + 'name' => 123 + ]); + } + + public function testEventIsCheckName() + { + $v = new TestValidate(); + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('用户名不是admin'); + $v->scene('checkName')->check([ + 'name' => 123 + ]); + } + + public function testBeforeThrowError() + { + $v = new TestValidate(); + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('error'); + $v->scene('beforeThrowError')->check([]); + } + /** * @test 测试使用事件设置默认值 * @throws ValidateException -- Gitee From 526c657f4746ff7da7b5e564d2f160874c4a2189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 28 May 2021 11:40:33 +0800 Subject: [PATCH 086/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=80=BC=EF=BC=8C=E5=8F=AF=E7=94=A8=E4=BA=8E=E4=B8=BA?= =?UTF-8?q?=E5=8D=B3=E5=B0=86=E8=A6=81=E9=AA=8C=E8=AF=81=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E8=AE=BE=E5=AE=9A=E9=BB=98=E8=AE=A4=E5=80=BC=E6=88=96?= =?UTF-8?q?=E8=80=85=E6=8F=90=E5=89=8D=E6=A0=BC=E5=BC=8F=E5=8C=96=E7=AD=89?= =?UTF-8?q?=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/ValidateScene.php | 53 ++++++++++-- src/Validate.php | 104 ++++++++++++++++++++-- tests/Test/TestDataDefault.php | 152 +++++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+), 16 deletions(-) create mode 100644 tests/Test/TestDataDefault.php diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 75ac8c9..6fd0c54 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -12,6 +12,7 @@ namespace W7\Validate\Support; +use Closure; use Illuminate\Support\Arr; use RuntimeException; use W7\Validate\Support\Rule\BaseRule; @@ -21,9 +22,10 @@ use W7\Validate\Support\Storage\ValidateCollection; * Class ValidateScene * @package W7\Validate\Support * - * @property-read array $events Events to be processed - * @property-read array $afters Methods to be executed after validation - * @property-read array $befores Methods to be executed before validation + * @property-read array $events Events to be processed for this validate + * @property-read array $befores Methods to be executed before this validate + * @property-read array $afters Methods to be executed after this validate + * @property-read array $defaults This validation requires a default value for the value * @property-read bool $eventPriority Event Priority */ class ValidateScene extends RuleManagerScene @@ -35,23 +37,29 @@ class ValidateScene extends RuleManagerScene protected $checkData = []; /** - * Events to be processed + * Events to be processed for this validate * @var array */ - protected $events = []; + private $events = []; /** - * Methods to be executed after validation + * Methods to be executed before this validate * @var array */ - protected $afters = []; + private $befores = []; /** - * Methods to be executed before validation + * Methods to be executed after this validate * @var array */ - protected $befores = []; + private $afters = []; + /** + * This validation requires a default value for the value + * @var array + */ + private $defaults = []; + /** * Event Priority * @var bool @@ -147,6 +155,33 @@ class ValidateScene extends RuleManagerScene return $this; } + /** + * Set a default value for the specified field + * + * @param string $field Name of the data field to be processed + * @param callable|Closure|mixed $callback The default value or an anonymous function that returns the default value which will + * be assigned to the attributes being validated if they are empty. The signature of the anonymous function + * should be as follows,The anonymous function has two parameters: + *
    + *
  • `$value` the data of the current field
  • + *
  • `$originalData` all the original data of the current validation
  • + *
+ * + * e.g: + * + * function($value,$originalData){ + * return $value; + * } + * + * @param bool $any Whether to handle arbitrary values, default only handle values that are not null + * @return $this + */ + public function default(string $field, $callback, bool $any = false): ValidateScene + { + $this->defaults[$field] = ['value' => $callback, 'any' => $any]; + return $this; + } + /** * Set event priority * diff --git a/src/Validate.php b/src/Validate.php index 2ac72ad..15ebd0d 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -12,6 +12,7 @@ namespace W7\Validate; +use Closure; use Illuminate\Validation\Factory; use Illuminate\Validation\ValidationException; use LogicException; @@ -19,6 +20,7 @@ use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Concerns\MessageProviderInterface; use W7\Validate\Support\Event\ValidateEventAbstract; use W7\Validate\Support\MessageProvider; +use W7\Validate\Support\Storage\ValidateCollection; use W7\Validate\Support\Storage\ValidateConfig; use W7\Validate\Support\ValidateScene; @@ -42,8 +44,16 @@ class Validate extends RuleManager */ protected $filled = true; + /** + * The filter. This can be a global function name, anonymous function, etc. + * @var array + */ protected $filter = []; + /** + * Sets the specified property to the specified default value. + * @var array + */ protected $default = []; /** @@ -53,23 +63,29 @@ class Validate extends RuleManager private $eventPriority = true; /** - * Validator event handling class + * Events to be processed for this validate * @var array */ private $events = []; /** - * Methods to be executed before validation + * Methods to be executed before this validate * @var array */ private $befores = []; /** - * Methods to be executed after validation + * Methods to be executed after this validate * @var array */ private $afters = []; + /** + * This validation requires a default value for the value + * @var array + */ + private $defaults = []; + /** * Error Message Provider * @var MessageProviderInterface @@ -121,8 +137,9 @@ class Validate extends RuleManager $this->init(); $this->checkData = $data; $this->addEvent($this->event); - $rule = $this->getCheckRules($this->getInitialRules()); - + $this->defaults = array_merge($this->default, $this->defaults); + $rule = $this->getCheckRules($this->getInitialRules()); + $data = $this->handleDefault($data, $rule); if ($this->filled) { $rule = $this->addFilledRule($rule); } @@ -186,6 +203,7 @@ class Validate extends RuleManager $this->event = array_merge($this->event, $scene->events); $this->afters = array_merge($this->afters, $scene->afters); $this->befores = array_merge($this->befores, $scene->befores); + $this->defaults = array_merge($this->defaults, $scene->defaults); $this->eventPriority = $scene->eventPriority; return $scene->getRules(); } @@ -307,7 +325,7 @@ class Validate extends RuleManager $handler = new $callback(...$param); $handler->sceneName = $this->getCurrentSceneName(); $handler->data = $data; - if (($result = call_user_func([$handler, $method])) !== true) { + if (true !== call_user_func([$handler, $method])) { $message = $handler->message; if (isset($this->message[$message])) { $message = $this->getMessageProvider()->handleMessage($this->message[$message]); @@ -320,14 +338,86 @@ class Validate extends RuleManager } } + /** + * Processing the set defaults + * + * @param array $data + * @param array $rule + * @return array + */ + private function handleDefault(array $data, array $rule): array + { + if (empty($this->defaults)) { + return $data; + } + + $newData = validate_collect($data); + $fields = array_keys($rule); + $defaults = array_intersect_key($this->defaults, array_flip($fields)); + foreach ($defaults as $field => $value) { + // Skip array members + if (false !== strpos($field, '*')) { + continue; + } + + if (is_array($value) && isset($value['any']) && isset($value['value'])) { + $this->setDefaultData($field, $value['value'], $newData, (bool)$value['any']); + } else { + $this->setDefaultData($field, $value, $newData); + } + } + + return $newData->toArray(); + } + + /** + * Applying default settings to data + * + * @param string $field Name of the data field to be processed + * @param callable|Closure|mixed $callback the default value or an anonymous function that returns the default value which will + * be assigned to the attributes being validated if they are empty. The signature of the anonymous function + * should be as follows,The anonymous function has two parameters: + *
    + *
  • `$value` the data of the current field
  • + *
  • `$originalData` all the original data of the current validation
  • + *
+ * + * e.g: + * + * function($value,$originalData){ + * return $value; + * } + * + * @param ValidateCollection $data Data to be processed + * @param bool $any Whether to handle arbitrary values, default only handle values that are not null + */ + private function setDefaultData(string $field, $callback, ValidateCollection $data, bool $any = false) + { + $isEmpty = function ($value) { + return null === $value || [] === $value || '' === $value; + }; + $value = $data->get($field); + if (!$data->has($field) || $isEmpty($value) || true === $any) { + if (is_callable($callback)) { + $value = call_user_func($callback, $value, $this->checkData); + } elseif (is_string($callback) && method_exists($this, 'default' . ucfirst($callback))) { + $value = call_user_func([$this, 'default' . ucfirst($callback)], $value, $this->checkData); + } else { + $value = $callback; + } + } + $data->set($field, $value); + } + /** * Initialization validate */ private function init() { - $this->handlers = []; + $this->events = []; $this->afters = []; $this->befores = []; + $this->defaults = []; $this->eventPriority = true; } diff --git a/tests/Test/TestDataDefault.php b/tests/Test/TestDataDefault.php new file mode 100644 index 0000000..3e24a25 --- /dev/null +++ b/tests/Test/TestDataDefault.php @@ -0,0 +1,152 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Exception\ValidateException; +use W7\Validate\Support\ValidateScene; +use W7\Validate\Validate; + +class TestDataDefault extends BaseTestValidate +{ + public function testDefaultIsScalar() + { + $v = new class extends Validate { + protected $rule = [ + 'name' => 'required' + ]; + + protected $default = [ + 'name' => '123' + ]; + }; + + $data = $v->check([]); + + $this->assertEquals('123', $data['name']); + } + + public function testDefaultIsArray() + { + $v = new class extends Validate { + protected $rule = [ + 'name' => 'required' + ]; + + protected $default = [ + 'name' => ['a', 'b', 'any' => 123] + ]; + }; + + $data = $v->check([]); + + $this->assertEquals(['a', 'b', 'any' => 123], $data['name']); + + $v = new class extends Validate { + protected $rule = [ + 'name' => 'required' + ]; + + protected $default = [ + 'name' => ['value' => ['a', 'b'], 'any' => true] + ]; + }; + + $data = $v->check([]); + + $this->assertEquals(['a', 'b'], $data['name']); + } + + public function testDefaultIsCallback() + { + $v = new class extends Validate { + protected $rule = [ + 'name' => 'required', + 'age' => 'required|numeric', + 'sex' => 'required' + ]; + + public function __construct() + { + $this->default = [ + 'name' => function ($value) { + return '小张'; + }, + 'age' => [$this, 'setAge'], + 'sex' => 'setSex' + ]; + } + + public function setAge($value) + { + return 100; + } + + public function defaultSetSex($value) + { + return '男'; + } + }; + + $data = $v->check([]); + + $this->assertEquals(['name' => '小张', 'age' => 100, 'sex' => '男'], $data); + } + + public function testHandlerData() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required' + ]; + + public function __construct() + { + $this->default = [ + 'id' => ['value' => function ($value) { + if (is_string($value)) { + return explode(',', $value); + } + return $value; + }, 'any' => true] + ]; + } + }; + + $data = $v->check([ + 'id' => '1,2,3,4' + ]); + + $this->assertEquals([1, 2, 3, 4], $data['id']); + } + + public function testDefaultForScene() + { + $v = new class extends Validate { + protected $rule = [ + 'name' => 'required' + ]; + + protected function sceneTest(ValidateScene $scene) + { + $scene->only(['name']) + ->default('name', '小张'); + } + }; + $this->expectException(ValidateException::class); + $v->check([]); + + $data = $v->scene('test')->check([]); + $this->assertEquals('小张', $data['name']); + } +} -- Gitee From 1f39a6393b9f0b2c1e69b246adf88bd927418d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 28 May 2021 16:31:10 +0800 Subject: [PATCH 087/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E5=99=A8=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E5=90=8E=E7=9A=84=E6=95=B0=E6=8D=AE=20[U]=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=A8=8B=E5=BA=8F=E8=BF=90=E8=A1=8C=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E5=BC=82=E5=B8=B8=E7=B1=BB=E4=B8=BAValidateRuntimeExc?= =?UTF-8?q?eption?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Exception/ValidateRuntimeException.php | 19 ++++ src/Support/Concerns/FilterInterface.php | 18 ++++ src/Support/ValidateScene.php | 32 ++++++ src/Validate.php | 108 ++++++++++++++++----- tests/Test/TestDataFilter.php | 104 ++++++++++++++++++++ 5 files changed, 257 insertions(+), 24 deletions(-) create mode 100644 src/Exception/ValidateRuntimeException.php create mode 100644 src/Support/Concerns/FilterInterface.php create mode 100644 tests/Test/TestDataFilter.php diff --git a/src/Exception/ValidateRuntimeException.php b/src/Exception/ValidateRuntimeException.php new file mode 100644 index 0000000..ee09e6c --- /dev/null +++ b/src/Exception/ValidateRuntimeException.php @@ -0,0 +1,19 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Exception; + +use RuntimeException; + +class ValidateRuntimeException extends RuntimeException +{ +} diff --git a/src/Support/Concerns/FilterInterface.php b/src/Support/Concerns/FilterInterface.php new file mode 100644 index 0000000..fb23c88 --- /dev/null +++ b/src/Support/Concerns/FilterInterface.php @@ -0,0 +1,18 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Concerns; + +interface FilterInterface +{ + public function handle($value); +} diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 6fd0c54..d02dc17 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -15,6 +15,7 @@ namespace W7\Validate\Support; use Closure; use Illuminate\Support\Arr; use RuntimeException; +use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\Storage\ValidateCollection; @@ -26,6 +27,7 @@ use W7\Validate\Support\Storage\ValidateCollection; * @property-read array $befores Methods to be executed before this validate * @property-read array $afters Methods to be executed after this validate * @property-read array $defaults This validation requires a default value for the value + * @property-read array $filters The filter. This can be a global function name, anonymous function, etc. * @property-read bool $eventPriority Event Priority */ class ValidateScene extends RuleManagerScene @@ -59,6 +61,12 @@ class ValidateScene extends RuleManagerScene * @var array */ private $defaults = []; + + /** + * The filter. This can be a global function name, anonymous function, etc. + * @var array + */ + private $filters = []; /** * Event Priority @@ -182,6 +190,30 @@ class ValidateScene extends RuleManagerScene return $this; } + /** + * Set a filter for the specified field + * + * Filter is a data processor. + * It invokes the specified filter callback to process the attribute value + * and save the processed value back to the attribute. + * @param string $field Name of the data field to be processed + * @param string|callable|Closure|FilterInterface $callback The filter. This can be a global function name, anonymous function, etc. + * The filter must be a valid PHP callback with the following signature: + * + * function foo($value) { + * // compute $newValue here + * return $newValue; + * } + * + * Many PHP functions qualify this signature (e.g. `trim()`). + * @return $this + */ + public function filter(string $field, $callback): ValidateScene + { + $this->filters[$field] = $callback; + return $this; + } + /** * Set event priority * diff --git a/src/Validate.php b/src/Validate.php index 15ebd0d..7e51ae0 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -13,10 +13,14 @@ namespace W7\Validate; use Closure; +use Illuminate\Support\Str; use Illuminate\Validation\Factory; +use Illuminate\Validation\ValidationData; use Illuminate\Validation\ValidationException; use LogicException; use W7\Validate\Exception\ValidateException; +use W7\Validate\Exception\ValidateRuntimeException; +use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Concerns\MessageProviderInterface; use W7\Validate\Support\Event\ValidateEventAbstract; use W7\Validate\Support\MessageProvider; @@ -86,6 +90,12 @@ class Validate extends RuleManager */ private $defaults = []; + /** + * Filters to be passed for this validation + * @var array + */ + private $filters = []; + /** * Error Message Provider * @var MessageProviderInterface @@ -137,9 +147,12 @@ class Validate extends RuleManager $this->init(); $this->checkData = $data; $this->addEvent($this->event); - $this->defaults = array_merge($this->default, $this->defaults); $rule = $this->getCheckRules($this->getInitialRules()); - $data = $this->handleDefault($data, $rule); + $fields = array_keys($rule); + $this->defaults = array_merge($this->default, $this->defaults); + $this->filters = array_merge($this->filter, $this->filters); + $data = $this->handleDefault($data, $fields); + if ($this->filled) { $rule = $this->addFilledRule($rule); } @@ -157,6 +170,7 @@ class Validate extends RuleManager } $data = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes)->validate(); + $data = $this->handlerFilter($data, $fields); if ($this->eventPriority) { $this->handleCallback($data, 2); @@ -204,6 +218,7 @@ class Validate extends RuleManager $this->afters = array_merge($this->afters, $scene->afters); $this->befores = array_merge($this->befores, $scene->befores); $this->defaults = array_merge($this->defaults, $scene->defaults); + $this->filters = array_merge($this->filters, $scene->filters); $this->eventPriority = $scene->eventPriority; return $scene->getRules(); } @@ -333,26 +348,83 @@ class Validate extends RuleManager throw new ValidateException($message, 403); } } else { - throw new ValidateException('Event error or nonexistence'); + throw new ValidateRuntimeException('Event error or nonexistence'); } } } /** - * Processing the set defaults + * Filters for processing settings * * @param array $data - * @param array $rule + * @param array $fields * @return array */ - private function handleDefault(array $data, array $rule): array + private function handlerFilter(array $data, array $fields): array + { + if (empty($this->filters)) { + return $data; + } + + $newData = validate_collect($data); + $filters = array_intersect_key($this->filters, array_flip($fields)); + foreach ($filters as $field => $callback) { + if (false !== strpos($field, '*')) { + $flatData = ValidationData::initializeAndGatherData($field, $data); + $pattern = str_replace('\*', '[^\.]*', preg_quote($field)); + foreach ($flatData as $key => $value) { + if (Str::startsWith($key, $field) || preg_match('/^' . $pattern . '\z/', $key)) { + $this->filterValue($key, $callback, $newData); + } + } + } else { + $this->filterValue($field, $callback, $newData); + } + } + + return $newData->toArray(); + } + + /** + * Filter the given value + * + * @param string $field Name of the data field to be processed + * @param callable|Closure|FilterInterface $callback The filter. This can be a global function name, anonymous function, etc. + * @param ValidateCollection $data + */ + private function filterValue(string $field, $callback, ValidateCollection $data) + { + $value = $data->get($field); + + if (is_callable($callback)) { + $value = call_user_func($callback, $value); + } elseif (class_exists($callback) && is_subclass_of($callback, FilterInterface::class)) { + /** @var FilterInterface $filter */ + $filter = new $callback; + $value = $filter->handle($value); + } elseif (is_string($callback) && method_exists($this, 'filter' . ucfirst($callback))) { + $value = call_user_func([$this, 'filter' . ucfirst($callback)], $value); + } else { + throw new ValidateRuntimeException('The provided filter is wrong'); + } + + $data->set($field, $value); + } + + /** + * Defaults for processing settings + * + * @param array $data + * @param array $fields + * @return array + */ + private function handleDefault(array $data, array $fields): array { if (empty($this->defaults)) { return $data; } $newData = validate_collect($data); - $fields = array_keys($rule); $defaults = array_intersect_key($this->defaults, array_flip($fields)); foreach ($defaults as $field => $value) { // Skip array members @@ -374,22 +446,9 @@ class Validate extends RuleManager * Applying default settings to data * * @param string $field Name of the data field to be processed - * @param callable|Closure|mixed $callback the default value or an anonymous function that returns the default value which will - * be assigned to the attributes being validated if they are empty. The signature of the anonymous function - * should be as follows,The anonymous function has two parameters: - *
    - *
  • `$value` the data of the current field
  • - *
  • `$originalData` all the original data of the current validation
  • - *
- * - * e.g: - * - * function($value,$originalData){ - * return $value; - * } - * - * @param ValidateCollection $data Data to be processed - * @param bool $any Whether to handle arbitrary values, default only handle values that are not null + * @param callable|Closure|mixed $callback The default value or an anonymous function that returns the default value which will + * @param ValidateCollection $data Data to be processed + * @param bool $any Whether to handle arbitrary values, default only handle values that are not null */ private function setDefaultData(string $field, $callback, ValidateCollection $data, bool $any = false) { @@ -418,6 +477,7 @@ class Validate extends RuleManager $this->afters = []; $this->befores = []; $this->defaults = []; + $this->filters = []; $this->eventPriority = true; } @@ -439,7 +499,7 @@ class Validate extends RuleManager $this->setMessageProvider($messageProvider); return $this; } else { - throw new ValidateException('The provided message processor needs to implement the MessageProviderInterface interface'); + throw new ValidateRuntimeException('The provided message processor needs to implement the MessageProviderInterface interface'); } return $this; diff --git a/tests/Test/TestDataFilter.php b/tests/Test/TestDataFilter.php new file mode 100644 index 0000000..6766882 --- /dev/null +++ b/tests/Test/TestDataFilter.php @@ -0,0 +1,104 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Support\Concerns\FilterInterface; +use W7\Validate\Validate; + +class UniqueFilter implements FilterInterface +{ + public function handle($value) + { + return array_unique($value); + } +} +class TestDataFilter extends BaseTestValidate +{ + public function testSetFilterIsSystemMethod() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required|numeric' + ]; + + protected $filter = [ + 'id' => 'intval' + ]; + }; + + $data = $v->check(['id' => '1']); + + $this->assertTrue(1 === $data['id']); + } + + public function testSetFilterIsClassMethod() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required' + ]; + + protected $filter = [ + 'id' => 'toArray' + ]; + + public function filterToArray($value) + { + return explode(',', $value); + } + }; + + $data = $v->check(['id' => '1,2,3,4,5']); + + $this->assertEquals([1, 2, 3, 4, 5], $data['id']); + } + + public function testSetFilterIsFilterClass() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required|array', + 'id.*' => 'numeric' + ]; + + protected $filter = [ + 'id' => UniqueFilter::class + ]; + }; + + $data = $v->check(['id' => [1, 1, 2, 3, 4, 4, 5, 6, 7]]); + + $this->assertEquals([1, 2, 3, 4, 5, 6, 7], array_values($data['id'])); + } + + public function testSetFilterForArrayField() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required|array', + 'id.*' => 'numeric' + ]; + + protected $filter = [ + 'id.*' => 'intval' + ]; + }; + + $data = $v->check(['id' => ['1', '2', 3, '4']]); + + foreach ($data['id'] as $id) { + $this->assertEquals('integer', gettype($id)); + } + } +} -- Gitee From 33dbf62fc722ced0193aad1bf87fa14e4d7872c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 28 May 2021 16:50:53 +0800 Subject: [PATCH 088/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E5=85=B3?= =?UTF-8?q?=E4=BA=8E=E4=BA=8B=E4=BB=B6=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Material/HandlerDataValidate.php | 83 --------------- tests/Test/TestHandlerEvent.php | 50 --------- tests/Test/TestHandlerFunction.php | 134 +++++++++---------------- 3 files changed, 45 insertions(+), 222 deletions(-) delete mode 100644 tests/Material/HandlerDataValidate.php diff --git a/tests/Material/HandlerDataValidate.php b/tests/Material/HandlerDataValidate.php deleted file mode 100644 index b0bd5cc..0000000 --- a/tests/Material/HandlerDataValidate.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Tests\Material; - -use W7\Validate\Support\ValidateScene; -use W7\Validate\Validate; - -class HandlerDataValidate extends Validate -{ - protected $rule = [ - 'user' => 'required|array', - 'user.*' => 'chsAlphaNum', - 'name' => 'required|Chs' - ]; - - protected $customAttributes = [ - 'name' => '名称' - ]; - - protected $scene = [ - 'afterRule' => ['user', 'user.*', 'after' => 'checkUserNotRepeat'], - 'addData' => ['user', 'user.*', 'after' => 'addData'], - 'beforeHandlerData' => ['name', 'before' => 'setDefaultName'], - 'beforeSetDefaultNameIsError' => ['name', 'before' => 'setDefaultNameIsError'] - ]; - - public function sceneBeforeHandlerDataScene(ValidateScene $scene) - { - $scene->only(['name']) - ->before('setDefaultName'); - } - - public function sceneBeforeSetDefaultNameIsErrorScene(ValidateScene $scene) - { - $scene->only(['name']) - ->before('setDefaultNameIsError'); - } - - public function afterAddData(array $data, $next) - { - $data['user'][] = 'c'; - return $next($data); - } - - public function afterCheckUserNotRepeat(array $data, $next) - { - $uniqueData = array_unique($data['user']); - - if (count($data['user']) === count($uniqueData)) { - return $next($data); - } - - return '用户信息重复'; - } - - public function beforeSetDefaultName(array $data, $next) - { - if (!isset($data['name']) || empty($data['name'])) { - $data['name'] = '张三'; - } - - return $next($data); - } - - public function beforeSetDefaultNameIsError(array $data, $next) - { - if (isset($data['name']) || empty($data['name'])) { - $data['name'] = 'test'; - } - - return $next($data); - } -} diff --git a/tests/Test/TestHandlerEvent.php b/tests/Test/TestHandlerEvent.php index 81448cc..8939077 100644 --- a/tests/Test/TestHandlerEvent.php +++ b/tests/Test/TestHandlerEvent.php @@ -46,54 +46,4 @@ class TestHandlerEvent extends BaseTestValidate $this->expectExceptionMessage('error'); $v->scene('beforeThrowError')->check([]); } - - /** - * @test 测试使用事件设置默认值 - * @throws ValidateException - */ - public function testEventSetDefault() - { - $v = new HandlerEventValidate(); - - $data = $v->scene('setDefault')->check([ - 'a' => 567 - ]); - - $this->assertEquals(567, $data['a']); - $this->assertEquals(2, $data['b']); - } - - /** - * @test 测试使用事件来使指定的字段递增 - * @throws ValidateException - */ - public function testIncreasing() - { - $v = new HandlerEventValidate(); - - $data = $v->scene('incr')->check([ - 'i' => 1 - ]); - - $this->assertEquals(2, $data['i']); - } - - /** - * @test 测试当验证场景中使用了use,被use的场景中的事件是否生效 - * @throws ValidateException - */ - public function testUseSceneForIncreasing() - { - $v = new HandlerEventValidate(); - - $data = $v->scene('useIncr')->check([ - 'i' => 1 - ]); - - $this->assertEquals(2, $data['i']); - - $data = $v->scene('useIncr')->check($data); - - $this->assertEquals(3, $data['i']); - } } diff --git a/tests/Test/TestHandlerFunction.php b/tests/Test/TestHandlerFunction.php index b9f59e9..6a4e224 100644 --- a/tests/Test/TestHandlerFunction.php +++ b/tests/Test/TestHandlerFunction.php @@ -15,96 +15,52 @@ namespace W7\Tests\Test; use W7\Tests\Material\HandlerDataValidate; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; +use W7\Validate\Validate; class TestHandlerFunction extends BaseTestValidate { - /** - * @test 测试在after中进行最后的验证 - * @throws ValidateException - */ - public function testAfterRule() - { - $v = new HandlerDataValidate(); - - $this->expectExceptionMessage('用户信息重复'); - - $v->scene('afterRule')->check(['user' => [ - 'a', 'a' - ]]); - } - - /** - * @test 测试在after方法中对数据进行处理 - * @throws ValidateException - */ - public function testAfterAddData() - { - $v = new HandlerDataValidate(); - - $data = $v->scene('addData')->check(['user' => [ - 'a', 'b' - ]]); - - $this->assertCount(3, $data['user']); - } - - /** - * @test 测试在before方法中对值设定一个默认值 - * @throws ValidateException - */ - public function testBeforeHandlerData() - { - $v = new HandlerDataValidate(); - - $data = $v->scene('beforeHandlerData')->check([]); - - $this->assertEquals('张三', $data['name']); - - $data = $v->scene('beforeHandlerData')->check(['name' => '李四']); - - $this->assertEquals('李四', $data['name']); - } - - /** - * @test 测试在before方法中对值设定一个不符合规则的默认值 - * @throws ValidateException - */ - public function testBeforeHandlerToVerifySetDefaultValues() - { - $v = new HandlerDataValidate(); - - $this->expectExceptionMessage('名称的值只能具有中文'); - - $v->scene('beforeSetDefaultNameIsError')->check([]); - } - - /** - * @test 测试在before方法中对值设定一个默认值 - 自定义验证场景 - * @throws ValidateException - */ - public function testBeforeHandlerData2() - { - $v = new HandlerDataValidate(); - - $data = $v->scene('beforeHandlerDataScene')->check([]); - - $this->assertEquals('张三', $data['name']); - - $data = $v->scene('beforeHandlerDataScene')->check(['name' => '李四']); - - $this->assertEquals('李四', $data['name']); - } - - /** - * @test 测试在before方法中对值设定一个不符合规则的默认值 - 自定义验证场景 - * @throws ValidateException - */ - public function testBeforeHandlerToVerifySetDefaultValues2() - { - $v = new HandlerDataValidate(); - - $this->expectExceptionMessage('名称的值只能具有中文'); - - $v->scene('beforeSetDefaultNameIsErrorScene')->check([]); - } + public function testAfterFunction(){ + $v = new class extends Validate{ + protected $rule = [ + 'id' => 'required' + ]; + + protected $scene = [ + 'testAfter' => ['id','after' => 'checkId'] + ]; + + protected function afterCheckId($data){ + if ($data['id'] < 0){ + return "ID错误"; + } + return true; + } + }; + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage("ID错误"); + + $v->scene("testAfter")->check(['id' => -1]); + } + + public function testBeforeFunction(){ + $v = new class extends Validate{ + protected $rule = [ + 'id' => 'required' + ]; + + protected $scene = [ + 'testBefore' => ['id','before' => 'checkSiteStatus'] + ]; + + protected function beforeCheckSiteStatus(array $data){ + return "站点未开启"; + } + }; + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage("站点未开启"); + + $v->scene("testBefore")->check([]); + } } -- Gitee From 4cd7d09f6dfac0add98ffef2950928f09d111e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 31 May 2021 15:46:28 +0800 Subject: [PATCH 089/152] =?UTF-8?q?[A]=20=E9=BB=98=E8=AE=A4=E5=80=BC?= =?UTF-8?q?=E5=92=8C=E8=BF=87=E6=BB=A4=E5=99=A8=E5=A2=9E=E5=8A=A0=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/ValidateScene.php | 22 +++++++++++++++------- src/Validate.php | 11 +++++++---- tests/Test/TestDataDefault.php | 25 +++++++++++++++++++++++++ tests/Test/TestDataFilter.php | 25 +++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 11 deletions(-) diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index d02dc17..d7d538f 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -166,27 +166,33 @@ class ValidateScene extends RuleManagerScene /** * Set a default value for the specified field * - * @param string $field Name of the data field to be processed - * @param callable|Closure|mixed $callback The default value or an anonymous function that returns the default value which will + * @param string $field Name of the data field to be processed + * @param callable|Closure|mixed|null $callback The default value or an anonymous function that returns the default value which will * be assigned to the attributes being validated if they are empty. The signature of the anonymous function * should be as follows,The anonymous function has two parameters: *
    *
  • `$value` the data of the current field
  • + *
  • `$attribute` current field name
  • *
  • `$originalData` all the original data of the current validation
  • *
* * e.g: * - * function($value,$originalData){ + * function($value,string $attribute,array $originalData){ * return $value; * } * - * @param bool $any Whether to handle arbitrary values, default only handle values that are not null + * If this parameter is null, the default value of the field will be removed + * @param bool $any Whether to handle arbitrary values, default only handle values that are not null * @return $this */ public function default(string $field, $callback, bool $any = false): ValidateScene { - $this->defaults[$field] = ['value' => $callback, 'any' => $any]; + if (null === $callback) { + $this->defaults[$field] = null; + } else { + $this->defaults[$field] = ['value' => $callback, 'any' => $any]; + } return $this; } @@ -196,8 +202,8 @@ class ValidateScene extends RuleManagerScene * Filter is a data processor. * It invokes the specified filter callback to process the attribute value * and save the processed value back to the attribute. - * @param string $field Name of the data field to be processed - * @param string|callable|Closure|FilterInterface $callback The filter. This can be a global function name, anonymous function, etc. + * @param string $field Name of the data field to be processed + * @param string|callable|Closure|FilterInterface|null $callback The filter. This can be a global function name, anonymous function, etc. * The filter must be a valid PHP callback with the following signature: * * function foo($value) { @@ -206,6 +212,8 @@ class ValidateScene extends RuleManagerScene * } * * Many PHP functions qualify this signature (e.g. `trim()`). + * + * If this parameter is null, the filter for this field will be cancelled. * @return $this */ public function filter(string $field, $callback): ValidateScene diff --git a/src/Validate.php b/src/Validate.php index 7e51ae0..9787e6a 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -369,6 +369,9 @@ class Validate extends RuleManager $newData = validate_collect($data); $filters = array_intersect_key($this->filters, array_flip($fields)); foreach ($filters as $field => $callback) { + if (null === $callback) { + continue; + } if (false !== strpos($field, '*')) { $flatData = ValidationData::initializeAndGatherData($field, $data); $pattern = str_replace('\*', '[^\.]*', preg_quote($field)); @@ -428,7 +431,7 @@ class Validate extends RuleManager $defaults = array_intersect_key($this->defaults, array_flip($fields)); foreach ($defaults as $field => $value) { // Skip array members - if (false !== strpos($field, '*')) { + if (null === $value || false !== strpos($field, '*')) { continue; } @@ -456,11 +459,11 @@ class Validate extends RuleManager return null === $value || [] === $value || '' === $value; }; $value = $data->get($field); - if (!$data->has($field) || $isEmpty($value) || true === $any) { + if ($isEmpty($value) || true === $any) { if (is_callable($callback)) { - $value = call_user_func($callback, $value, $this->checkData); + $value = call_user_func($callback, $value, $field, $this->checkData); } elseif (is_string($callback) && method_exists($this, 'default' . ucfirst($callback))) { - $value = call_user_func([$this, 'default' . ucfirst($callback)], $value, $this->checkData); + $value = call_user_func([$this, 'default' . ucfirst($callback)], $value, $field, $this->checkData); } else { $value = $callback; } diff --git a/tests/Test/TestDataDefault.php b/tests/Test/TestDataDefault.php index 3e24a25..c4477ad 100644 --- a/tests/Test/TestDataDefault.php +++ b/tests/Test/TestDataDefault.php @@ -149,4 +149,29 @@ class TestDataDefault extends BaseTestValidate $data = $v->scene('test')->check([]); $this->assertEquals('小张', $data['name']); } + + public function testCancelDefaultValue() + { + $v = new class extends Validate { + protected $rule = [ + 'name' => '' + ]; + + protected $default = [ + 'name' => 1 + ]; + + protected function sceneTest(ValidateScene $scene) + { + $scene->only(['name']) + ->default('name', null); + } + }; + + $data = $v->check([]); + $this->assertEquals(1, $data['name']); + + $data = $v->scene('test')->check([]); + $this->assertArrayNotHasKey('name', $data); + } } diff --git a/tests/Test/TestDataFilter.php b/tests/Test/TestDataFilter.php index 6766882..0efa7d2 100644 --- a/tests/Test/TestDataFilter.php +++ b/tests/Test/TestDataFilter.php @@ -14,6 +14,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Support\Concerns\FilterInterface; +use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; class UniqueFilter implements FilterInterface @@ -101,4 +102,28 @@ class TestDataFilter extends BaseTestValidate $this->assertEquals('integer', gettype($id)); } } + + public function testCancelFilter() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required' + ]; + + protected $filter = [ + 'id' => 'intval' + ]; + + protected function sceneTest(ValidateScene $scene) + { + $scene->only(['id']) + ->filter('id', null); + } + }; + + $data = $v->check(['id' => '你好']); + $this->assertEquals(0, $data['id']); + $data = $v->scene('test')->check(['id' => '你好']); + $this->assertEquals('你好', $data['id']); + } } -- Gitee From e5e2ecb97db05c719ec965d3731235aa110fac41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 31 May 2021 17:45:28 +0800 Subject: [PATCH 090/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c98cbd1..b5b6012 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,17 @@ 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 ## 说明 -此验证基于Laravel的Validator验证器,可用于Laravel,软擎等依赖于illuminate/validation的项目中,此验证器做了如下扩展: +此验证基于`illuminate/validation`做了如下扩展 - - 可通过类的方式定义一个[验证器](https://v.neww7.com/3/Validate.html) - - 增加[验证场景](https://v.neww7.com/3/Scene.html) - - 增加[场景事件处理](https://v.neww7.com/3/Event.html) - - 增加[规则管理器](#),你可以单独的它 - - 修改了[自定义验证规则](https://v.neww7.com/3/Rule.html) - - [自定义消息](https://v.neww7.com/3/Message.html) 增加了对内容的引用等 - - 继承集合类增加一个[验证集合](https://v.neww7.com/3/Collection.html) - -等...使您的验证只需要在验证器中全部都可以完成 +- 可通过类的方式定义一个[验证器](https://v.neww7.com/3/Validate.html) +- 增加[验证场景](https://v.neww7.com/3/Scene.html) +- 增加[规则管理器](https://v.neww7.com/3/RuleManager.html) +- 增加数据[默认值](https://v.neww7.com/3/Default.html) +- 增加数据[过滤器](https://v.neww7.com/3/Filter.html) +- 增加[场景事件](https://v.neww7.com/3/Event.html) +- 修改了[自定义验证规则](https://v.neww7.com/3/Rule.html) +- [自定义消息](https://v.neww7.com/3/Message.html) 增加了对内容的引用 +- 继承集合类增加一个[验证集合](https://v.neww7.com/3/Collection.html) > 验证器支持Laravel的内置规则,内置规则文档可查看[规则文档](https://learnku.com/docs/laravel/7.x/validation/5144#c58a91) -- Gitee From c1569cbbd95b119913ed547a510bdddc9872b9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 1 Jun 2021 11:34:09 +0800 Subject: [PATCH 091/152] =?UTF-8?q?[A]=20Default=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=AF=B9=E7=B1=BB=E7=9A=84=E6=94=AF=E6=8C=81=20[F]=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8DDefault=E5=92=8CFilter=E5=BD=93callback=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=98=AF=E6=95=B0=E7=BB=84=E6=97=B6=E5=87=BA=E7=8E=B0?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Concerns/DefaultInterface.php | 18 ++++++++++++++++ src/Support/ValidateScene.php | 7 +++--- src/Validate.php | 15 ++++++++----- tests/Test/TestDataDefault.php | 26 +++++++++++++++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 src/Support/Concerns/DefaultInterface.php diff --git a/src/Support/Concerns/DefaultInterface.php b/src/Support/Concerns/DefaultInterface.php new file mode 100644 index 0000000..edfa416 --- /dev/null +++ b/src/Support/Concerns/DefaultInterface.php @@ -0,0 +1,18 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support\Concerns; + +interface DefaultInterface +{ + public function handle($value, string $attribute, array $originalData); +} diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index d7d538f..669d20b 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -15,6 +15,7 @@ namespace W7\Validate\Support; use Closure; use Illuminate\Support\Arr; use RuntimeException; +use W7\Validate\Support\Concerns\DefaultInterface; use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\Storage\ValidateCollection; @@ -166,8 +167,8 @@ class ValidateScene extends RuleManagerScene /** * Set a default value for the specified field * - * @param string $field Name of the data field to be processed - * @param callable|Closure|mixed|null $callback The default value or an anonymous function that returns the default value which will + * @param string $field Name of the data field to be processed + * @param callable|Closure|mixed|DefaultInterface|null $callback The default value or an anonymous function that returns the default value which will * be assigned to the attributes being validated if they are empty. The signature of the anonymous function * should be as follows,The anonymous function has two parameters: *
    @@ -183,7 +184,7 @@ class ValidateScene extends RuleManagerScene * } * * If this parameter is null, the default value of the field will be removed - * @param bool $any Whether to handle arbitrary values, default only handle values that are not null + * @param bool $any Whether to handle arbitrary values, default only handle values that are not null * @return $this */ public function default(string $field, $callback, bool $any = false): ValidateScene diff --git a/src/Validate.php b/src/Validate.php index 9787e6a..2ec49df 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -20,6 +20,7 @@ use Illuminate\Validation\ValidationException; use LogicException; use W7\Validate\Exception\ValidateException; use W7\Validate\Exception\ValidateRuntimeException; +use W7\Validate\Support\Concerns\DefaultInterface; use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Concerns\MessageProviderInterface; use W7\Validate\Support\Event\ValidateEventAbstract; @@ -401,7 +402,7 @@ class Validate extends RuleManager if (is_callable($callback)) { $value = call_user_func($callback, $value); - } elseif (class_exists($callback) && is_subclass_of($callback, FilterInterface::class)) { + } elseif ((is_string($callback) || is_object($callback)) && class_exists($callback) && is_subclass_of($callback, FilterInterface::class)) { /** @var FilterInterface $filter */ $filter = new $callback; $value = $filter->handle($value); @@ -448,10 +449,10 @@ class Validate extends RuleManager /** * Applying default settings to data * - * @param string $field Name of the data field to be processed - * @param callable|Closure|mixed $callback The default value or an anonymous function that returns the default value which will - * @param ValidateCollection $data Data to be processed - * @param bool $any Whether to handle arbitrary values, default only handle values that are not null + * @param string $field Name of the data field to be processed + * @param callable|Closure|DefaultInterface|mixed $callback The default value or an anonymous function that returns the default value which will + * @param ValidateCollection $data Data to be processed + * @param bool $any Whether to handle arbitrary values, default only handle values that are not null */ private function setDefaultData(string $field, $callback, ValidateCollection $data, bool $any = false) { @@ -462,6 +463,10 @@ class Validate extends RuleManager if ($isEmpty($value) || true === $any) { if (is_callable($callback)) { $value = call_user_func($callback, $value, $field, $this->checkData); + } elseif ((is_string($callback) || is_object($callback)) && class_exists($callback) && is_subclass_of($callback, DefaultInterface::class)) { + /** @var DefaultInterface $default */ + $default = new $callback(); + $value = $default->handle($value, $field, $this->checkData); } elseif (is_string($callback) && method_exists($this, 'default' . ucfirst($callback))) { $value = call_user_func([$this, 'default' . ucfirst($callback)], $value, $field, $this->checkData); } else { diff --git a/tests/Test/TestDataDefault.php b/tests/Test/TestDataDefault.php index c4477ad..3de1a52 100644 --- a/tests/Test/TestDataDefault.php +++ b/tests/Test/TestDataDefault.php @@ -14,9 +14,18 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; +use W7\Validate\Support\Concerns\DefaultInterface; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; +class SetDefaultIsHello implements DefaultInterface +{ + public function handle($value, string $attribute, array $originalData) + { + return "Hello"; + } +} + class TestDataDefault extends BaseTestValidate { public function testDefaultIsScalar() @@ -174,4 +183,21 @@ class TestDataDefault extends BaseTestValidate $data = $v->scene('test')->check([]); $this->assertArrayNotHasKey('name', $data); } + + public function testDefaultUseDefaultClass() + { + $v = new class extends Validate + { + protected $rule = [ + 'name' => '' + ]; + + protected $default = [ + 'name' => SetDefaultIsHello::class + ]; + }; + + $data = $v->check([]); + $this->assertEquals("Hello", $data['name']); + } } -- Gitee From 2eca33b4c7fb2753b63782ecfb3875a37a25467a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 3 Jun 2021 11:34:23 +0800 Subject: [PATCH 092/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E8=BD=AF?= =?UTF-8?q?=E6=93=8E=E6=A1=86=E6=9E=B6=E4=B8=AD=E8=8E=B7=E5=8F=96=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=99=A8=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateConfig.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 770d4cd..3cd7e1e 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -110,7 +110,7 @@ final class ValidateConfig $this->factory = App::make('validator'); break; case 2: - $this->factory = \W7\Facade\Container::singleton("W7\Contract\Validation\ValidatorFactoryInterface"); + $this->factory = \W7\Facade\Container::get("W7\Contract\Validation\ValidatorFactoryInterface"); break; default: throw new RuntimeException('Framework Type Error'); -- Gitee From 212d81c0cdd958489912f2832f8bf9bf90854994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 4 Jun 2021 11:02:03 +0800 Subject: [PATCH 093/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=B6=88=E6=81=AF=E5=AF=B9=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=90=8D=E7=A7=B0=E7=9A=84=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/MessageProvider.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Support/MessageProvider.php b/src/Support/MessageProvider.php index 0d24762..7e45c1a 100644 --- a/src/Support/MessageProvider.php +++ b/src/Support/MessageProvider.php @@ -118,6 +118,13 @@ class MessageProvider implements MessageProviderInterface $message = str_replace($pregString, Arr::get($this->data, $matches[1][$index], ''), $message); } } + + if (preg_match_all('/@{(.*?)}/', $message, $matches) > 0) { + foreach ($matches[0] as $index => $pregString) { + $message = str_replace($pregString, $this->customAttributes[$matches[1][$index]] ?? '', $message); + } + } + return $message; } } -- Gitee From 2dc638ef9464f5b592e2e8ae598342723ef2f402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 4 Jun 2021 11:08:28 +0800 Subject: [PATCH 094/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=B6=88=E6=81=AF=E5=AF=B9=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E5=90=8D=E7=A7=B0=E5=BC=95=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Test/TestValidateMessage.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/Test/TestValidateMessage.php b/tests/Test/TestValidateMessage.php index 535fa6c..2e11743 100644 --- a/tests/Test/TestValidateMessage.php +++ b/tests/Test/TestValidateMessage.php @@ -21,6 +21,7 @@ class TestMessage extends RuleManager protected $rule = [ 'user' => 'required|email', 'pass' => 'required|lengthBetween:6,16', + 're_pass' => 'required|eq:pass', 'name' => 'required|chs|lengthBetween:2,4', 'remark' => 'required|alpha_dash', 'captcha' => 'required|length:4|checkCaptcha', @@ -29,12 +30,14 @@ class TestMessage extends RuleManager protected $message = [ 'user.required' => '用户名必须填写', 'user.email' => '你输入的:{:user},不是有效的:attribute', - 'pass.required' => '密码必须填写' + 'pass.required' => '密码必须填写', + 're_pass.eq' => '你输入的@{pass}与:attribute不一致' ]; protected $customAttributes = [ 'user' => '用户名', 'pass' => '密码', + 're_pass' => '确认密码', 'name' => '昵称', 'remark' => '备注', 'captcha' => '验证码', @@ -61,5 +64,7 @@ class TestValidateMessage extends BaseTestValidate $this->assertEquals('你输入的:123456,不是有效的:attribute', $message->setData([ 'user' => '123456' ])->getMessage('user', 'email')); + + $this->assertEquals('你输入的密码与:attribute不一致', $message->getMessage('re_pass','eq')); } } -- Gitee From 3a121c7dbe223dd64d74c30b66baf598579522e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 4 Jun 2021 11:11:19 +0800 Subject: [PATCH 095/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96PHP=E7=9A=84=E6=89=A9=E5=B1=95=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 4 ++-- tests/Test/TestValidateMessage.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 0b17fc3..84dea01 100644 --- a/composer.json +++ b/composer.json @@ -20,9 +20,9 @@ "illuminate/validation": "^6.0|^7.0|^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.18", "laravel-lang/lang": "^8.0", - "phpunit/phpunit": "^8.5" + "phpunit/phpunit": "^8.5", + "friendsofphp/php-cs-fixer": "^3.0" }, "autoload": { "psr-4": { diff --git a/tests/Test/TestValidateMessage.php b/tests/Test/TestValidateMessage.php index 2e11743..6e2dd97 100644 --- a/tests/Test/TestValidateMessage.php +++ b/tests/Test/TestValidateMessage.php @@ -65,6 +65,6 @@ class TestValidateMessage extends BaseTestValidate 'user' => '123456' ])->getMessage('user', 'email')); - $this->assertEquals('你输入的密码与:attribute不一致', $message->getMessage('re_pass','eq')); + $this->assertEquals('你输入的密码与:attribute不一致', $message->getMessage('re_pass', 'eq')); } } -- Gitee From d56d23df653037bd1c042533d111fd446ebb24f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 10 Jun 2021 11:53:38 +0800 Subject: [PATCH 096/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1373 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1372 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b5b6012..20ac4f3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # 增强表单验证 +## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 ## 说明 @@ -22,4 +23,1374 @@ composer require w7/engine-validate ``` -完整文档查看[完整文档](https://v.neww7.com) \ No newline at end of file +完整文档查看[完整文档](https://v.neww7.com) + +# 验证器 +## 简单验证 +支持简单定义一个验证器并进行验证: +```php +try { + $data = Validate::make([ + 'user' => 'required|email', + 'pass' => 'required|lengthBetween:6,16', + ], [ + 'user.required' => '请输入用户名', + 'user.email' => '用户名格式错误', + 'pass.required' => '请输入密码', + 'pass.lengthBetween' => '密码长度为6~16位', + ])->check($data); +} catch (ValidateException $e) { + echo $e->getMessage(); +} +``` +如果验证通过,则返回所有通过验证的值,如未通过,则抛出一个`W7\Validate\Exception\ValidateException`异常 + +## 验证器定义 +为具体的验证场景或者数据表单定义验证器类,我们需要继承`W7\Validate\Validate`类,然后实例化后直接调用验证类的`check`方法即可完成验证,下面是一个例子: + +我们定义一个`LoginValidate`验证器类用于登录的验证。 +```php +class LoginValidate extends Validate +{ + protected $rule = [ + 'user' => 'required|email', + 'pass' => 'required|digits_between:6,16', + ]; + + protected $message = [ + 'user.required' => '请输入用户名', + 'user.email' => '用户名格式错误', + 'pass.required' => '请输入密码', + 'pass.digits_between' => '密码长度为6~16位', + ]; +} + +``` + +>
    类属性定义的错误消息,优先级要高于自定义规则中的默认回复,高于自定义规则方法返回的错误
    + +## 数据验证 +``` php +$data = [ + 'user' => '123@qq.com', + 'pass' => '' +]; +$validate = new LoginValidate(); +$validate->check($data); +``` +此时会抛出一个`W7\Validate\Exception\ValidateException`异常,message为`请输入密码` +``` php +$data = [ + 'user' => '123@qq.com', + 'pass' => '123456' +]; +$validate = new LoginValidate(); +$data = $validate->check($data); +``` +验证成功,并返回通过验证的值,返回的值为数组类型 + +## 验证数组 +验证表单的输入为数组的字段也不难。你可以使用 「点」方法来验证数组中的属性。例如,如果传入的 HTTP 请求中包含`search[keyword]`字段, 可以如下验证: +``` php +protected $rule = [ + 'search.order' => 'numeric|between:1,2', + 'search.keyword' => 'chsAlphaNum', + 'search.recycle' => 'boolean', +]; +``` +你也可以验证数组中的每个元素。例如,要验证指定数组输入字段中的每一个 id 是唯一的,可以这么做: +``` php +protected $rule = [ + 'search.*.id' => 'numeric|unique:account' +]; +``` +数组规则的错误消息的定义也一样 +``` php +protected $message = [ + 'search.order.numeric' => '排序参数错误', + 'search.order.between' => '排序参数错误', + 'search.keyword.chsAlphaNum' => '关键词只能包含中文,字母,数字', + 'search.recycle.boolean' => '参数错误:recycle', +]; +``` +## 验证器类属性 +### $rule +用户定义验证器的验证规则,也可以通过`setRules`方法来进行设置,此方法为叠加,如果参数为`null`则为清空全部规则 +```php +// 类中定义 +protected $rule = [ + 'user' => 'required' +]; + +// 使用方法定义 +$v->setRules([ + 'user' => 'required' +]); +``` +### $message +用户定义验证器的错误信息,也可以通过`setMessages`方法来进行设置,此方法为叠加,如果参数为`null`则为清空全部错误消息 +```php +// 类中定义 +protected $message = [ + 'user.required' => '账号必须填写' +]; + +// 使用方法定义 +$v->setMessages([ + 'user.required' => '账号必须填写' +]); +``` +### $scene +定义验证场景的数据,用于指定验证场景对应的验证字段等,详细用法查看[验证场景](https://v.neww7.com/3/Scene.html)一节,同样也可以通过`setScene`方法来进行设置,此方法为叠加,如果参数为`null`则为清空全部验证场景 +```php +// 类中定义 +protected $scene = [ + 'login' => ['user', 'pass'] +]; + +// 使用方法定义 +$v->setScene([ + 'login' => ['user', 'pass'] +]); +``` +### $event +定义此验证器下的全局事件,详细用法查看[事件](https://v.neww7.com/3/Event.html)一节 +```php +protected $event = [ + CheckSiteStatus::class +]; +``` +### $customAttributes +定义验证字段的名称,也可以通过`setCustomAttributes`方法来进行设置,此方法为叠加,如果参数为`null`则为清空全部字段名称, +错误消息中的[:attribute](https://v.neww7.com/3/Message.html#attribute)会使用下面的值对应的替换 +```php +protected $customAttributes = [ + 'user' => '账号', + 'pass' => '密码' +]; +``` +### $default +定义字段的默认值 +```php +protected $default = [ + 'name' => '张三' +]; +``` +关于默认值的详情请查看[默认值](https://v.neww7.com/3/Default.html)一节 +### $filter +用于数据验证后处理数据 +```php +protected $filter = [ + 'name' => 'trim' +]; +``` +关于过滤器的详情请查看[过滤器](https://v.neww7.com/3/Filter.html)一节 +### $bail +是否首次验证失败后停止运行,如果此属性值为`true`,所有规则会自动增加`bail`规则,默认为`true` +```php +protected $bail = true; +``` +### $filled +所有验证的字段在存在时不能为空,如果此属性值为`true`,所有规则会自动增加`filled`规则,默认为`true` + +当出现以下情况时,不会自动添加`filled`规则 +- 验证规则中存在`filled`, `nullable`, `accepted`, `present`,`required`, `required_if`, `required_unless`, `required_with`,`required_with_all`, `required_without`, `required_without_all`规则 +- 验证规则存在[extendImplicit](https://v.neww7.com/3/Rule.html#extendimplicit-隐式扩展)定义的规则 +- 验证规则实现了[ImplicitRule](https://v.neww7.com/3/Rule.html#implicitrule-隐式规则对象)标记接口 +```php +protected bool $filled = true; +``` + +# 验证场景 +## 验证场景 +[规则管理器](https://v.neww7.com/3/RuleManager.html)和[验证器](https://v.neww7.com/3/Validate.html)均支持定义场景,验证不同场景的数据,例如: +``` php +class ArticleValidate extends Validate +{ + protected $rule = [ + 'id' => 'required|numeric', + 'content' => 'required|digits_between:1,2000', + 'title' => 'required|digits_between:4,50|alpha', + ]; + + protected $message = [ + 'id.required' => '缺少参数:文章Id', + 'id.numeric' => '参数错误:文章Id', + 'content.required' => '文章内容必须填写', + 'content.digits_between' => '文章长度为1~2000个字符', + 'title.required' => '文章标题必须填写', + 'title.digits_between' => '文章标题格式错误', + 'title.alpha' => '文章标题长度为4~50个字符', + ]; + + protected $scene = [ + 'add' => ['content','title'], + 'edit' => ['id','content','title'], + 'del' => ['id'], + ]; +} +``` +然后可以在验证方法中使用验证的场景,使用`scene`方法指定验证场景 +``` php +$data = [ + 'content' => '内容', + 'title' => '这是一个标题' +]; +$validate = new ArticleValidate(); +$data = $validate->scene('add')->check($data); +``` +## 验证场景复用 +有时候验证场景中的字段,要求都一样的时候,可以使用`use`关键词使用验证器 + +> 请注意:[规则管理器](https://v.neww7.com/3/RuleManager.html)不支持验证场景复用 +``` php +protected $scene = [ + 'edit' => ['id','content','title'], + 'save' => ['use' => 'edit'], +]; +``` +``` php +$validate = new ArticleValidate(); +$validate->scene('save')->check($data); +``` +这里是`save`场景,实际上是用的`edit`场景字段 +>
    如都定义了中间件,则都生效
    + + +`use`关键词也支持传入自定义方法 +``` php +protected $scene = [ + 'save' => ['type','use' = 'selectSaveScene'], + 'saveSetting' => ['id','name'] +] + + +protected function useSelectSaveScene(array $data) +{ + return 'save'.$data['type']; +} +``` + +>自定义方法的参数 +自定义方法会有一个数组类型的参数,传入的参数为第一次验证后的数据,也就是除去`use`字段的其他字段,返回字符串为使用对应的验证场景,返回数组为使用对应的验证字段 + +## 自定义验证场景 +可以单独为某个场景定义方法(方法的命名规范是`scene`+ 首字母大写的场景名),方法提供一个[场景类](https://v.neww7.com/3/Scene.html#场景类的方法),可用于对某些字段的规则重新设置,例如: + +- 在[规则管理器](https://v.neww7.com/3/RuleManager.html)中的场景类为:`W7\Validate\Support\RuleManagerScene` +- 在[验证器](https://v.neww7.com/3/Validate.html)中的场景类为:`W7\Validate\Support\ValidateScene` + +> 注意 +场景名在调用的时候不能将驼峰写法转为下划线 + + +``` php +protected function sceneEdit($scene) +{ + $scene->only(['id','content','title']) + ->append('id',"max") + ->remove("content",'between') + ->remove('title',null) + ->append('title','required|between|alpha'); +} +``` +> 说明 +`scene`验证场景在调用`check`方法以后会被重置,并不会对下一次`check`生效 + +## 验证字段为数组 +在验证器中,支持对数组下的元素进行定义规则,在验证场景中,同样支持指定验证数组元素 +规则的定义如下: +``` php +protected $rule = [ + 'search.order' => 'numeric|between:1,2', + 'search.keyword' => 'chsAlphaNum', + 'search.recycle' => 'boolean', +]; +``` +验证场景定义: +``` php +protected $scene = [ + 'list' => ['search.order','search.keyword','search.recycle'] +]; +``` +## 场景类的方法 +[验证器](https://v.neww7.com/3/Validate.html)的场景类方法说明如下: + +| 方法名 | 描述 | +| --- | --- | +| [only](https://v.neww7.com/3/Scene.html#only) | 场景中需要验证的字段 | +| [remove](https://v.neww7.com/3/Scene.html#remove) | 移除场景中的字段的部分验证规则 | +| [append](https://v.neww7.com/3/Scene.html#append) | 给场景中的字段追加验证规则 | +| [sometimes](https://v.neww7.com/3/Scene.html#sometimes) | 复杂条件验证| +| [event](https://v.neww7.com/3/Scene.html#event)|指定事件处理类| +| [getData](https://v.neww7.com/3/Scene.html#getdata)|获取当前验证的数据| +| [getValidateData](https://v.neww7.com/3/Scene.html#getvalidatedata)|作用同[getData](https://v.neww7.com/3/Scene.html#getdata),区别在于,此方法返回一个[验证器集合](https://v.neww7.com/3/Collection.html)类| +| [before](https://v.neww7.com/3/Scene.html#before)|添加一个验证前的需要执行的方法| +| [after](https://v.neww7.com/3/Scene.html#after)|添加一个验证后需要执行的方法| +| [appendCheckField](https://v.neww7.com/3/Scene.html#appendcheckfield)|添加一个需要验证的字段| +| [removeCheckField](https://v.neww7.com/3/Scene.html#removecheckfield)|删除一个需要验证的字段| +| [setEventPriority](https://v.neww7.com/3/Scene.html#seteventpriority)|设置事件和简易事件的优先级| +| [default](https://v.neww7.com/3/Scene.html#default)| 设置或取消一个字段的默认值| +| [filter](https://v.neww7.com/3/Scene.html#filter)|设置或取消一个字段的过滤器| + +[规则管理器](https://v.neww7.com/3/RuleManager.html)的场景类方法说明如下: + +| 方法名 | 描述 | +| --- | --- | +| [only](https://v.neww7.com/3/Scene.html#only) | 场景中需要验证的字段 | +| [remove](https://v.neww7.com/3/Scene.html#remove) | 移除场景中的字段的部分验证规则 | +| [append](https://v.neww7.com/3/Scene.html#append) | 给场景中的字段追加验证规则 | +| [appendCheckField](https://v.neww7.com/3/Scene.html#appendcheckfield)|添加一个需要验证的字段| +| [removeCheckField](https://v.neww7.com/3/Scene.html#removecheckfield)|删除一个需要验证的字段| + +### only +指定场景需要验证的字段 +```php +public function only(array $fields): $this +``` +- `$fields` 为要验证的字段数组 + +### remove +移除场景中的字段的部分验证规则 +``` php +public function remove(string $field, string $rule = null): $this +``` +- `$field` 为要移除规则的字段 +- `$rule` 为要移除的规则,多个规则用`|`分割,也可填入规则数组,`$rule`如为`null`,则清空该字段下的所有规则 + +### append +给场景中的字段需要追加验证规则 +``` php +public function append(string $field, string $rule): $this +``` +- `$field` 为要追加规则的字段 +- `$rule` 为要追加的规则,多个规则用`|`分割,也可填入规则数组 + +### sometimes +复杂条件验证 + +有时候你可能需要增加基于更复杂的条件逻辑的验证规则。例如,你可以希望某个指定字段在另一个字段的值超过 100 时才为必填。或者当某个指定字段存在时,另外两个字段才能具有给定的值 +``` php +public function sometimes($attribute, $rules, callable $callback): $this +``` +- `$attribute` 要追加规则的字段,多个可传数组 +- `$rules` 要追加的规则,多个规则用`|`分割,也可填入规则数组 +- `$callback` 闭包方法,如果其返回`true`, 则额外的规则就会被加入 +> 参数:传入 闭包 的`$data`参数是`W7\Validate\Support\Storage\ValidateCollection`的一个实例,可用来访问你的输入或文件对象。 + + +我们可以根据一个参数或多个来处理其他参数的验证条件,更灵活的实现验证: +``` php +$scene->sometimes("name","required",function ($data) { + return $data->type === 1; +}); +``` + +### event +指定[场景事件](https://v.neww7.com/3/Event.html)处理类,一个场景可以使用多个[场景事件](https://v.neww7.com/3/Event.html)处理类 +``` php +public function event(string $handler, ...$params): $this +``` +- `$handler` 处理器命名空间,可使用`:class`进行传入 +- `$params` 传递给中间件构建方法的参数,不限数量 +### getData +此方法用来获取当前验证的数据 +```php +public function getData(string $key = '', $default = null) +``` +默认获取全部验证的值 +### getValidateData +此方法用来获取当前验证的数据,作用同[getData](https://v.neww7.com/3/Scene.html#getdata),区别在于,此方法返回一个[验证器集合](https://v.neww7.com/3/Collection.html)类 +```php +public function getValidateData(): ValidateCollection +``` +### before +添加一个验证前的需要执行的方法,方法仅限本类的方法,方法的命名规则为`before`加方法名,方法的定义查看[简单使用](https://v.neww7.com/3/Event.html#简单使用) +```php +public function before(string $callbackName, ...$params): $this +``` +- `$callbackName` 本类的方法名,不带前缀 +- `$params` 要传递给方法的参数 +### after +添加一个验证后需要执行的方法,方法仅限本类的方法,方法的命名规则为`after`加方法名,方法的定义查看[简单使用](https://v.neww7.com/3/Event.html#简单使用) +```php +public function after(string $callbackName, ...$params): $this +``` +- `$callbackName` 本类的方法名,不带前缀 +- `$params` 要传递给方法的参数 +### appendCheckField +添加一个需要验证的字段,当需要根据Sql或者其他各种条件来增加一个需要验证的字段时,你就需要用到`appendCheckField`这个方法 +```php +public function appendCheckField(string $field): $this +``` +- `$field` 需要添加的字段名称 +### removeCheckField +删除一个需要验证的字段,当需要根据Sql或者其他各种条件来删除一个正在验证的字段时,你就需要用到`removeCheckField`这个方法 +```php +public function removeCheckField(string $field): $this +``` +- `$field` 需要删除的字段名称 +### setEventPriority +设置[事件](https://v.neww7.com/3/Event.html)和[简易事件](https://v.neww7.com/3/Event.html#简单使用)的优先级 +```php +public function setEventPriority(bool $priority): Validate +``` +- 当值为True时,执行顺序为:`事件类beforeValidate`->`简易事件before`->`开始数据验证`->`简易事件after`->`事件类afterValidate` +- 当值为False时,执行顺序为:`简易事件before`->`事件类beforeValidate`->`开始数据验证`->`事件类afterValidate`->`简易事件after` +### default +设置或取消一个字段的[默认值](https://v.neww7.com/3/Default.html) +```php +public function default(string $field, $callback, bool $any = false): $this +``` +- `$field` 字段名称 +- `$callback` 默认值或者匿名函数等,如果为`null`,则取消该字段的默认值 +- `$any` 是否处理任意值,默认只处理空值 +### filter +设置或取消一个字段的[过滤器](https://v.neww7.com/3/Filter.html) +```php +public function filter(string $field, $callback): $this +``` +- `$field` 字段名称 +- `$callback` 全局函数名,匿名函数,过滤器类或其他 + +# 自定义规则 +## 前置处理 +使用自定义验证规则之前,必须先定义自定义验证规则的命名空间前缀 +``` php +ValidateConfig::instance()->rulesPath('W7\\App\\Model\\Validate\\Rules\\'); +``` +建议在`Provider`中定义验证相关的设置 +## 使用规则对象 +验证器内有很多有用的验证规则;同时也支持自定义规则。注册自定义验证规则的方法之一,就是新建一个规则并继承`W7\Validate\Support\Rule\BaseRule`。新的规则存放在你[设置好的目录](https://v.neww7.com/3/Start.html#配置自定义规则类路径)中 + +一旦创建了规则,我们就可以定义它的行为。 `passes`方法接收属性值和名称,并根据属性值是否符合规则而返回`true`或`false`。 `message`属性为验证失败时使用的验证错误消息,此错误消息可被验证器中定义的`message`覆盖: + +``` php +namespace W7\App\Model\Validate\Rules; + +class Chs extends BaseRule +{ + /** + * 默认错误消息 + * @var string + */ + protected $message = ':attribute的值只能具有中文'; + + /** + * 确定验证规则是否通过。 + * + * @param mixed $attribute + * @param mixed $value + * @return bool + */ + public function passes($attribute, $value): bool + { + return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$value); + } +} +``` +一旦规则对象被定义好后,你可以通过将规则对象的实例和其他验证规则一起来传递给验证器: +``` php +protected $rule = [ + 'title' => 'required|chs', +]; +``` +>
    自定义扩展规则首字母可小写,也建议使用小写
    + +### 自定义规则传入参数 +自定义规则,和其他规则一样,也支持传入参数,类似于`max:100`,`in:0,1,2`此类,参数将按顺序传入自定义规则类中的构造函数中,如下: +```php {7} +class Length extends BaseRule +{ + protected $message = ':attribute的长度不符合要求'; + + protected $size; + + public function __construct(int $size) + { + $this->size = $size; + } + + public function passes($attribute, $value): bool + { + return strlen($value) === $this->size; + } +} + +``` + +### 格式化错误消息 +在[上诉代码](https://v.neww7.com/3/Rule.html#自定义规则传入参数)中,错误提示可能并不是那么清晰,将`$size`变量放入错误提示,也许会更好,我们提供了`$messageParam`参数,用于支持格式化错误消息,如下: +```php {10} +class Length extends BaseRule +{ + protected $message = ':attribute的长度需为%d个字节'; + + protected $size; + + public function __construct(int $size) + { + $this->size = $size; + $this->messageParam = [$size]; + } + + public function passes($attribute, $value): bool + { + return strlen($value) === $this->size; + } +} + +``` +`$messageParam`是一个数组类型,所以传入的值必须为数组,如使用规则为`length:10`,则触发后的消息为:`:attribute的长度需为10个字节` + +`$message`字段定义: + +| 格式化格式 | 说明 | +| --- | --- | +| %% | 返回一个百分号 %| +| %b | 二进制数| +| %c | ASCII 值对应的字符| +| %d | 包含正负号的十进制数(负数、0、正数)| +| %e | 使用小写的科学计数法(例如 1.2e+2)| +| %E | 使用大写的科学计数法(例如 1.2E+2)| +| %u | 不包含正负号的十进制数(大于等于 0)| +| %f | 浮点数(本地设置)| +| %F | 浮点数(非本地设置)| +| %g | 较短的 %e 和 %f| +| %G | 较短的 %E 和 %f| +| %o | 八进制数| +| %s | 字符串| +| %x | 十六进制数(小写字母)| +| %X | 十六进制数(大写字母)| + +附加的格式值。必需放置在 % 和字母之间(例如 %.2f): + +- `\+` (在数字前面加上 + 或 - 来定义数字的正负性。默认情况下,只有负数才做标记,正数不做标记) +- `'` (规定使用什么作为填充,默认是空格。它必须与宽度指定器一起使用。例如:%'x20s(使用 "x" 作为填充)) +- `\-` (左调整变量值) +- `[0-9]` (规定变量值的最小宽度) +- `.[0-9]` (规定小数位数或最大字符串长度) + +> 注意 如果使用多个上述的格式值,`$messageParam`的参数必须按照上面的顺序进行使用,不能打乱。 + +关于错误消息的更多支持请查看[自定义错误消息](https://v.neww7.com/3/Message.html) +## 使用扩展 +### extend 扩展方法 +注册自定义的验证规则的另一种方法是使用`Validate`中的 `extend `方法。让我们在[验证器](https://v.neww7.com/3/Validate.html)中使用这个方法来注册自定义验证规则: +``` php +public function __construct() +{ + self::extend("check_admin",function($attribute, $value, $parameters, $validator){ + return $value === "owner"; + }); +} +``` +自定义的验证闭包接收四个参数:要被验证的属性名称 `$attribute`、属性的值 `$value`、传入验证规则的参数数组 `$parameters` 、以及 `Validator` 实例。 +除了使用闭包,你也可以传入类和方法到`extend`方法中: +``` php +Validate::extend("check_admin","permissionValidate@checkAdmin"); +``` +> 请注意 +传入类和方法需要指定方法为`public`类型,类要传入完整的命名空间,如果你的方法为静态方法,还可以通过数组形式进行传入[完整类名,方法名],如方法名没有传,则默认方法名为`validate` + +### 使用类方法 +自定义规则也支持直接使用当前验证器类下的方法,规则为`rule` + 规则名,如`ruleCheckLogin` + +> 请注意 这里的`checkLogin`和当前验证器下的其他方法注册的规则名不能重复,否则会覆盖 + +自定义规则方法类方法接收四个参数:要被验证的属性名称 `$attribute`、属性的值 `$value`、传入验证规则的参数数组 `$parameters` 、以及 `Validator` 实例。 +```php +class LoginValidate extends Validate +{ + protected $rule = [ + 'user' => 'required|alphaNum|checkLogin' + ]; + + protected $message = [ + 'user.checkLogin' => '登录失败' + ]; + + public function ruleCheckLogin($attribute, $value, $parameters, $validator): bool + { + return 'admin' === $value; + } +} +``` +### replacer 错误信息替换器 +如果需要定义错误消息,可以在`extend`的第三个参数中填入,或通过`replacer`方法进行定义 +`replacer`方法接受两个参数`ruleName`和一个闭包参数,闭包接受四个参数:错误消息`$message`, 被验证的属性名称`$attribute`, 当前的规则名称`$rule`,传入验证规则的参数数组`$parameters` +```php +Validate::replacer("check_admin",function($message,$attribute,$rule,$parameters){ + return "自定义错误消息" +}); +``` +除了使用闭包以外,也支持传入类和方法到`replacer`方法中 +```php +Validate::replacer("check_admin","permissionValidate@checkAdminMessage"); +``` +> 请注意 +传入类和方法需要指定方法为`public`类型,类要传入完整的命名空间,不支持数组传递,如方法名没有传,则默认方法名为`replace` + +可以覆盖默认规则的自定义消息,如果要定义自定义方法的错误消息,一定要先定义错误规则`extend`,再定义错误消息`replacer` + + +使用方式同使用规则对象 +```php +protected $rule = [ + 'title' => 'required|chs|check_admin', +]; +``` +### extendImplicit 隐式扩展 +默认情况下,当所要验证的属性不存在或包含一个空字符串时,使用包含自定义扩展的正常的验证规则是不会执行的。例如,`unique` 规则将不会检验空字符串: +```php +$rules = ['name' => 'unique:users,name']; + +$input = ['name' => '']; + +// 验证通过 +``` +如果即使属性为空也要验证规则,则一定要暗示属性是必须的。要创建这样一个「隐式」扩展,可以使用 `Validate`中的`extendImplicit()` 方法: +```php +Validate::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) { + return $value == 'foo'; +}); +``` +>
    注意:「隐式」扩展只暗示该属性是必需的。至于它到底是缺失还是空值这取决于你。
    + +### ImplicitRule 隐式规则对象 +如果你想要在属性为空时执行规则对象,你应该实现 `Illuminate\Contracts\Validation\ImplicitRule` 接口。这个接口将充当验证器的「标记接口」;因此,它不包含你要实现的任何方法。 +### extendDependent 依赖性验证器 +如果想定义一个自定义扩展对数组进行验证时,我们会发现`extend`和`extendImplicit`均不会解析`*`,这个时候就需要用到`Validate`中的`extendDependent`方法: +```php +Validate::extendDependent('contains', function ($attribute, $value, $parameters, $validator) { + // 下面验证器传来的$parameters是['*.provider'],当我们暗示这个自定义规则是依赖性的时候 + // 验证器往往会按照我们要验证的原始属性,用当前的指数替换星号,所以*.provider会被替换成0.provider + // 现在我们可以使用Arr:get()来获取其他字段的值。 + // 所以这个自定义规则验证了属性值包含了其他给定属性的值。 + return str_contains($value,Arr::get($validator->getData(),$parameters[0])); +}); + +$v = new Validate($request); +$v->setRules([ + '*.email' => 'contains:*.provider' +])->check([ + [ + 'email' => '995645888@qq.com', 'provider' => 'qq.com' + ] +]); +``` +# 规则管理器 +## 介绍 +对验证的规则进行管理,[验证器](https://v.neww7.com/3/Validate.html)是规则管理器的子类,如果你仅需要对规则进行管理,可直接继承该类。 +```php +class UserRulesManager extends RuleManager +{ + protected $rule = [ + 'user' => 'required|email', + 'pass' => 'required|lengthBetween:6,16', + 'name' => 'required|chs|lengthBetween:2,4', + 'remark' => 'required|alpha_dash', + 'captcha' => 'required|length:4|checkCaptcha', + ]; + + protected $scene = [ + 'login' => ['user', 'pass'], + 'captcha' => ['captcha'] + ]; + + protected $customAttributes = [ + 'user' => '用户名', + 'pass' => '密码', + 'name' => '昵称', + 'remark' => '备注', + 'captcha' => '验证码', + ]; + + protected $message = [ + 'captcha.checkCaptcha' => '验证码错误', + 'user.email' => '用户名必须为邮箱', + 'pass.lengthBetween' => '密码长度错误' + ]; + + protected function sceneRegister(RuleManagerScene $scene) + { + return $scene->only(['user', 'pass', 'name', 'remark']) + ->remove('remark', 'required|alpha_dash') + ->append('remark', 'chs'); + } + + protected function sceneRegisterNeedCaptcha(RuleManagerScene $scene) + { + return $this->sceneRegister($scene)->appendCheckField('captcha'); + } + + public function ruleCheckCaptcha($att, $value): bool + { + return true; + } +} +``` +> 提示 +在规则管理器中,可以使用[自定义规则](https://v.neww7.com/3/Rule.html)一节中提到的方式来扩展规则和错误消息 + + +## 获取规则 +可以直接调用类的静态方法`get`来获取规则、错误消息、属性名称 +```php +public static function get($fields = null, bool $initial = false): array +``` +- `$fields` 要获取的字段名称,如果为null,则获取所有规则 +- `$initial` 是否获取原始规则,默认为false,即解析后的规则 +```php +UserRulesManager::get('user'); +``` +> 请注意 +如果想应用验证场景的规则,请实例化类后使用`scene`方法指定验证场景后再调用`get`方法 + +```php +(new UserRulesManager())->scene('register')->get('user'); +``` +将返回 +```php +Array +( + [0] => Array + ( + [user] => Array + ( + [0] => required + [1] => email + ) + + ) + + [1] => Array + ( + [user.email] => 用户名必须为邮箱 + ) + + [2] => Array + ( + [user] => 用户名 + ) + +) +``` +获取指定[验证场景](https://v.neww7.com/3/Scene.html)下所有的规则、错误消息、属性名称,可直接使用`getBySceneName`静态方法: +```php +UserRulesManager::getBySceneName('register'); +``` +也可以直接调用静态方法 +```php +UserRulesManager::register(); +``` +## 单独获取 +如果想单独的获取规则,错误消息,属性名称,你可以实例化规则管理器后使用下列方法: + +- `getRules` 获取规则 +- `getCustomAttributes` 获取属性名称 +- `getMessages` 获取错误消息 + +> 请注意 +`getRules`方法受`scene`方法影响,不同的场景下取出的规则可能不同 + +# 自定义错误消息 +在[验证器](https://v.neww7.com/3/Validate.html)中提到使用`$message`参数来定义验证的错误消息,此节详细介绍错误消息的定义 + +## message变量 +错误消息`$message`变量支持填入 +- `:attribute` 表示字段名称 +- `{:field}` 表示字段内容 + +> 说明:上述文本在[自定义规则](https://v.neww7.com/3/Rule.html)中均支持使用 + +### :attribute +`:attribute` 代表为当前触发错误的`customAttributes`变量中的字段名称 +```php +class Test extends Validate +{ + protected $rule = [ + 'user' => 'required' + ]; + + protected $message = [ + 'user.required' => '请填写:attribute' + ]; + + protected $customAttributes = [ + 'user' => '账号' + ]; +} +``` + +触发后,提示的消息为`请填写账号` + +### {:field} +`{:field}`中间的`field`为当前验证值的字段,如果指定字段不存在,则为空文本,支持获取数组,如`info.name`,代表获取`info`数组中的`name`参数,可无限下层 +```php +class Test extends Validate +{ + protected $rule = [ + 'name' => 'chs' + ]; + + protected $message = [ + 'name.chs' => '你填写的名字{:name}不是中国名字' + ]; +} +``` +输入数据`['name' => 'Rasmus Lerdorf']`,提示:`你填写的名字Rasmus Lerdorf不是中国名字` + +## customAttributes变量 +当我们定义了大量的验证字段和规则时,如果一个一个对应的编写错误消息,需要耗费大量的时间成本,这个时候,我们可以使用`$customAttributes`变量定义字段的名称。 + +当错误触发时,会自动替换默认错误消息中的`:attribute`文本 + +```php {7-9} +class User extends Validate +{ + protected $rule = [ + 'id' => 'required|numeric', + ]; + + protected $customAttributes = [ + 'id' => '字段ID', + ]; +} +``` +当错误触发时,会提示`字段ID 不可为空`,`字段ID 必须为数字` +customAttributes变量中也支持`{:field}`,如: +```php {2} +protected $customAttributes = [ + 'id' => '字段ID:{:id}', +]; +``` +如果传入`id`为`hello` + +此时触发后会提示`字段ID:hello 必须为数字` + +# 过滤器 +在验证后给输入值应用一个过滤器, 并在验证后把它赋值回原属性变量。 + +## 说明 +过滤器可以为全局函数名,匿名函数,过滤器类或其他,该函数的样式必须是: +```php +function ($value) { + return $newValue; +} +``` +有许多的PHP方法结构和`filter`需要的结构一致。 比如使用类型转换方法 (`intval`, `boolval`, ...) 来确保属性为指定的类型, 你可以简单的设置这些方法名而不是重新定义一个匿名函数 +## 使用 +### 类属性定义 +```php +class UserValidate extends Validate +{ + protected $rule = [ + 'id' => 'required|array', + 'id.*' => 'numeric' + ]; + + protected $filter = [ + 'id.*' => 'intval' + ]; +} + +$data = UserValidate::make()->check([ + 'id' => ['1', 2] +]); +var_dump($data); +``` +输出 +``` +array(1) { + 'id' => + array(4) { + [0] => + int(1) + [1] => + int(2) + } +} +``` +### 在验证场景中使用 +```php +class UserValidate extends Validate +{ + protected $rule = [ + 'id' => 'required|array', + 'id.*' => 'numeric' + ]; + + protected function sceneToInt(ValidateScene $scene) + { + $scene->only(['id', 'id.*']) + ->filter('id.*', 'intval'); + } +} + +$data = UserValidate::make()->scene('toInt')->check([ + 'id' => ['1', 2] +]); +var_dump($data); +``` +输出 +``` +array(1) { + 'id' => + array(2) { + [0] => + int(1) + [1] => + int(2) + } +} +``` +## 过滤器类 +创建一个过滤器类,需要实现`W7\Validate\Support\Concerns\FilterInterface`接口: +```php +class UniqueFilter implements FilterInterface +{ + public function handle($value) + { + return array_unique($value); + } +} + +class UserValidate extends Validate +{ + protected $rule = [ + 'id' => 'required|array', + 'id.*' => 'numeric' + ]; + + protected $filter = [ + 'id' => UniqueFilter::class + ]; +} + +$data = UserValidate::make()->scene('toInt')->check([ + 'id' => [1,2,1,2,3,3,4] +]); +var_dump($data); +``` +输出 +``` +array(1) { + 'id' => + array(4) { + [0] => + int(1) + [1] => + int(2) + [4] => + int(3) + [6] => + int(4) + } +} +``` +## 类方法 +过滤器也支持直接写入类方法的方式,(方法的命名规范是`filter`+ 首字母大写的名称) +```php +class UserValidate extends Validate +{ + protected $rule = [ + 'id' => 'required|array', + 'id.*' => 'numeric' + ]; + + protected $filter = [ + 'id' => 'uniqueFilter' + ]; + + public function filterUniqueFilter($value) + { + return array_unique($value); + } +} +``` +在验证场景中可以直接使用`[$this,'filterUniqueFilter']`来传递`callable` +# 默认值 +为空值分配默认值,在验证之前执行,当值为空数组,空字符以及`null`时判断为空。 + +> 请注意 +默认值不支持数组元素,也就是说:为`id.*`这种设定默认值是不支持的 + +## 使用 +### 类属性定义 +使用类的`$default`参数来为字段设定默认值 +```php {8-11} +class Setting extends Validate +{ + protected $rule = [ + 'site_status' => 'required|in:0,1', + 'register_status' => 'required|in:0,1' + ]; + + protected $default = [ + 'site_status' => 1, + 'register_status' => 1 + ]; +} + +$data = Setting::make()->check([]); +print_r($data); +//Array +//( +// [site_status] => 1 +// [register_status] => 1 +//) +``` +### 在验证场景中使用 +在类中增加一个`base`验证场景 +```php +class Setting extends Validate +{ + protected $rule = [ + 'site_status' => 'required|in:0,1', + 'register_status' => 'required|in:0,1' + ]; + + protected $default = [ + 'site_status' => 1, + 'register_status' => 1 + ]; + + protected function sceneBase(ValidateScene $scene) + { + $scene->only(['site_status']) + ->default('site_status', 0); + } +} +$data = Setting::make()->scene('base')->check([]); +print_r($data); +//Array +//( +// [site_status] => 1 +//) +``` +> 说明 +一个字段只能拥有一个默认值,验证场景中的默认值生效后,全局定义的默认值就失效。 + +默认值只对当前需要验证的字段生效 + +## 多样的默认值 +### 闭包 +默认值支持闭包,闭包将收到三个值 +- `$value` 当前的值 +- `$attribute` 当前的字段名 +- `$originalData` 当前正在进行验证的全部原始数据 + +回调方法的样式如下: +```php +function($value, string $attribute, array $originalData) { + return $value; +} +``` +示例: +```php +$scene->defalt('name', function($value) { + return '张三'; +}); +``` +### 类方法 +使用类方法为指定字段传递默认值时,同样会接受到三个值 +- `$value` 当前的值 +- `$attribute` 当前的字段名 +- `$originalData` 当前正在进行验证的全部原始数据 + +```php +$scene->defalt('name', [$this,'setDefaultName']); + +public function setDefaultName($value, string $attribute, array $originalData) +{ + return '张三'; +} +``` +简易方法: + +定义一个默认值方法,(方法的命名规范是`default`+ 首字母大写的名称) +```php +$scene->defalt('name','setDefaultName'); + +public function defaultSetDefaultName($value, string $attribute, array $originalData) +{ + return '张三'; +} +``` +### 忽略空条件 +当值为空数组,空字符以及`null`时,才会取出对应默认值并赋值到原数据上, +如果你想任何值都获取一次默认值,可以增加`any => true`的条件,如果增加了`any`,你需要将你的默认值放入`value`中,如下: +```php +class Setting extends Validate +{ + protected $rule = [ + 'site_status' => 'required|in:0,1', + ]; + + protected $default = [ + 'site_status' => ['value' => 1, 'any' => true], + ]; +} +``` +这个时候,无论`site_status`的原始参数是什么,都会被重置为`1`,你也可以使用该特性,为参数做提前格式化等操作 +### 取消默认值 +如果你想在验证场景中,取消[类属性中](https://v.neww7.com/3/Default.html#类属性定义)设定的默认值,可以将值设定为`null`,如下: +```php +class User extends Validate +{ + protected $rule = [ + 'name' => '' + ]; + + protected $default = [ + 'name' => '张三' + ]; + + protected function sceneTest(ValidateScene $scene) + { + $scene->only(['name']) + ->default('name', null); + } +} + +$data = User::make()->scene('test')->check([]); // 返回空数组 +``` +### 提供默认值的类 +创建一个提供默认值的类,需要实现`W7\Validate\Support\Concerns\DefaultInterface`接口: +```php +class DefaultUserId implements DefaultInterface +{ + public function handle($value, string $attribute, array $originalData) + { + return $_SESSION['user_id']; + } +} +``` +使用: +```php +class UserValidate extends Validate +{ + protected $rule = [ + 'id' => 'required', + ]; + + protected $default = [ + 'id' => DefaultUserId::class + ]; +} +``` +# 验证事件 +## 验证事件处理 +目前支持的验证事件为 +- 验证前事件`beforeValidate` +- 验证后事件`afterValidate` + +>
    事件仅支持在场景中定义使用
    + +验证器中间件需要继承`W7\Validate\Support\Event\ValidateEventAbstract` + +事件类拥有三个类属性 + +- `$sceneName` 当前的场景名称 +- `$data` 验证前的值或验证后的值 +- `$message` 错误消息,如果事件返回`false`,则验证器将取此值作为错误消息 + +```php +abstract class ValidateEventAbstract implements ValidateEventInterface +{ + public function beforeValidate(): bool; + public function afterValidate(): bool; +} +``` + +场景事件处理类构建函数中可以取到传递过来的值 + +如场景中使用了`event(CheckPermission::class,1,2,3)`,则构建函数 +```php +public function __construct($a,$b,$c) +{ + +} +``` +可依次获取到`$a = 1` `$b = 2` `$c = 3` + +## 使用方法 +### 在验证场景中 +可在验证场景中使用`event`关键词 + +如果不需要给场景事件处理类传值: +``` php +protected $scene = [ + 'add' => ['id','user_id','role','event' => CheckPermission::class], +]; +``` +如果需要给场景事件处理类传值: +``` php +protected $scene = [ + 'add' => ['id','user_id','role','event' => [ + CheckPermission::class=>[1,2,3,4] + ]], +]; +``` + +>
    传值的数量不限制,可在场景事件处理类的构建函数中获取
    + +### 在自定义验证场景中 +在自定义验证场景中,可使用`event`方法定义要使用的场景事件处理类,不限数量 +```php +/* +* @method $this event(string $handler,...$params) +*/ + +$scene->event(CheckPermission::class) +``` +如果要传值 +``` php +$scene->event(CheckPermission::class,1,2,3) +``` +使用多个场景事件处理类 +```php +$scene->event(CheckPermission::class,1,2,3)->event(CheckName::class) +``` +## 全局事件处理器 +如果你某个验证器中的所有场景都使用到共同的事件处理器,可以定义一个全局的事件处理器 +```php +protected $event = [ + CheckPermission::class => ['owner'] +]; +``` +可定义多个全局事件处理器,如果场景中也定义了事件处理器,则全部生效 + +## 简单使用 +如果你只是想在验证前给某个字段设置一个默认值或在每个字段验证后进行一个总的验证等需求,而此验证业务不需要复用, +可以直接`after`和`before`来进行简单定义。而不需要去定义一个类 + +在自定义验证场景中,可使用`after`和`before`方法定义要使用的事件处理方法,不限数量 +- `before` 在验证之前执行的方法 +- `after` 在验证之后执行的方法 + +方法接受一个验证数据`array $data`参数 + +与事件类`event`同用时的执行顺序为:`beforeValidate`->`before`->`after`->`afterValidate` + +> 如果想更改执行顺序,可以在[自定义验证场景](https://v.neww7.com/3/Scene.html#自定义验证场景)中使用[setEventPriority](https://v.neww7.com/3/Scene.html#seteventpriority)方法 + +方法仅限本类的方法,方法的命名规则为`after`或`before`加方法名,如: +```php +class LoginValidate extends \W7\Validate\Validate +{ + protected $rule = [ + 'name' => 'required|chs', + 'user' => 'required|alpha_dash', + 'pass' => 'required|min:8', + ]; + + protected $scene = [ + 'register' => ['name', 'user', 'pass', 'before' => 'checkRegisterStatus'] + ]; + + public function beforeCheckRegisterStatus(array $data) + { + return true; + } +} +``` +简单使用也可以为方法传递参数,传参方法同[使用方法](https://v.neww7.com/3/Event.html#使用方法),只不过要将类名换为方法名,第一个参数为当前验证的值或者验证后的值 +```php +protected $message = [ + 'user.required' => '用户名不可为空' +]; + +protected $scene = [ + 'register' => ['name', 'user', 'pass', 'before' => 'setDefaultName','after'=> [ + 'checkUserExist' => [1,2,3,4] + ]] +]; + +public function afterCheckUserExist(array $data,$a,$b,$c) +{ + return true; +} +``` +同样可依次获取到`$a = 1` `$b = 2` `$c = 3` + +> 返回值: +> 如果返回的是字符串,则抛出`W7\Validate\Exception\ValidateException`异常,代表未通过,如果通过,则返回`$next($data);` +> +> 事件中可以直接返回`message`的`key`值,如`user.required`,验证器会自动查找对应的错误消息。 + +# 自定义错误消息 +在[验证器](https://v.neww7.com/3/Validate.html)中提到使用`$message`参数来定义验证的错误消息,此节详细介绍错误消息的定义 + +## message变量 +错误消息`$message`变量支持填入 +- `:attribute` 表示字段名称 +- `{:field}` 表示字段内容 + +> 说明:上述文本在[自定义规则](https://v.neww7.com/3/Rule.html)中均支持使用 + +### :attribute +`:attribute` 代表为当前触发错误的`customAttributes`变量中的字段名称 +```php +class Test extends Validate +{ + protected $rule = [ + 'user' => 'required' + ]; + + protected $message = [ + 'user.required' => '请填写:attribute' + ]; + + protected $customAttributes = [ + 'user' => '账号' + ]; +} +``` + +触发后,提示的消息为`请填写账号` + +### {:field} +`{:field}`中间的`field`为当前验证值的字段,如果指定字段不存在,则为空文本,支持获取数组,如`info.name`,代表获取`info`数组中的`name`参数,可无限下层 +```php +class Test extends Validate +{ + protected $rule = [ + 'name' => 'chs' + ]; + + protected $message = [ + 'name.chs' => '你填写的名字{:name}不是中国名字' + ]; +} +``` +输入数据`['name' => 'Rasmus Lerdorf']`,提示:`你填写的名字Rasmus Lerdorf不是中国名字` + +## customAttributes变量 +当我们定义了大量的验证字段和规则时,如果一个一个对应的编写错误消息,需要耗费大量的时间成本,这个时候,我们可以使用`$customAttributes`变量定义字段的名称。 + +当错误触发时,会自动替换默认错误消息中的`:attribute`文本 + +```php {7-9} +class User extends Validate +{ + protected $rule = [ + 'id' => 'required|numeric', + ]; + + protected $customAttributes = [ + 'id' => '字段ID', + ]; +} +``` +当错误触发时,会提示`字段ID 不可为空`,`字段ID 必须为数字` +customAttributes变量中也支持`{:field}`,如: +```php {2} +protected $customAttributes = [ + 'id' => '字段ID:{:id}', +]; +``` +如果传入`id`为`hello` + +此时触发后会提示`字段ID:hello 必须为数字` -- Gitee From 2997b726c08178168d20b417c3789e03609510d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 11 Jun 2021 16:22:11 +0800 Subject: [PATCH 097/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E8=BF=87?= =?UTF-8?q?=E6=BB=A4=E5=99=A8=E4=BC=9A=E7=BB=99=E4=B8=8D=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=9A=84=E5=80=BC=E8=AE=BEnull=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 3 +++ tests/Test/TestDataFilter.php | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/Validate.php b/src/Validate.php index 2ec49df..b84a1d8 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -398,6 +398,9 @@ class Validate extends RuleManager */ private function filterValue(string $field, $callback, ValidateCollection $data) { + if (!$data->has($field)) { + return; + } $value = $data->get($field); if (is_callable($callback)) { diff --git a/tests/Test/TestDataFilter.php b/tests/Test/TestDataFilter.php index 0efa7d2..9050c7f 100644 --- a/tests/Test/TestDataFilter.php +++ b/tests/Test/TestDataFilter.php @@ -103,6 +103,22 @@ class TestDataFilter extends BaseTestValidate } } + public function testNotHasDataFilter() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'numeric' + ]; + + protected $filter = [ + 'id' => 'intval' + ]; + }; + + $data = $v->check([]); + $this->assertArrayNotHasKey('id', $data); + } + public function testCancelFilter() { $v = new class extends Validate { -- Gitee From 8559c3a0f04c1a4c189558b33b58ddb52869e8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 11 Jun 2021 16:34:55 +0800 Subject: [PATCH 098/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0=E8=BD=AF?= =?UTF-8?q?=E6=93=8E=E9=AA=8C=E8=AF=81=E4=B8=AD=E9=97=B4=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E9=80=82=E9=85=8D=E6=96=B0=E7=89=88=E6=9C=AC=E8=BD=AF=E6=93=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Middleware/Rangine/ValidateMiddleware.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Support/Middleware/Rangine/ValidateMiddleware.php b/src/Support/Middleware/Rangine/ValidateMiddleware.php index 921bb0b..8ce6f7b 100644 --- a/src/Support/Middleware/Rangine/ValidateMiddleware.php +++ b/src/Support/Middleware/Rangine/ValidateMiddleware.php @@ -15,7 +15,6 @@ namespace W7\Validate\Support\Middleware\Rangine; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; -use W7\Core\Route\Route; use W7\Facade\Context; use W7\Core\Middleware\MiddlewareAbstract; use W7\Http\Message\Server\Request; @@ -25,15 +24,8 @@ class ValidateMiddleware extends MiddlewareAbstract { public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { - /** @var Route $route */ - $route = $request->getAttribute('route'); - $routeHandler = $route->handler; - - if (!is_array($routeHandler) || 2 !== count($routeHandler)) { - throw new \RuntimeException('Routing information retrieval failed'); - } - - list($controller, $scene) = $routeHandler; + $controller = $request->route->getController(); + $scene = $request->route->getAction(); $validator = ValidateMiddlewareConfig::instance()->getValidateFactory()->getValidate($controller, $scene); -- Gitee From 96b1a6f34f8e2d446538d986edd72263b8f324bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 16 Jun 2021 19:18:17 +0800 Subject: [PATCH 099/152] =?UTF-8?q?[U]=20=E7=B2=BE=E7=AE=80=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1194 ----------------------------------------------------- 1 file changed, 1194 deletions(-) diff --git a/README.md b/README.md index 20ac4f3..a9de19c 100644 --- a/README.md +++ b/README.md @@ -200,1197 +200,3 @@ protected $bail = true; ```php protected bool $filled = true; ``` - -# 验证场景 -## 验证场景 -[规则管理器](https://v.neww7.com/3/RuleManager.html)和[验证器](https://v.neww7.com/3/Validate.html)均支持定义场景,验证不同场景的数据,例如: -``` php -class ArticleValidate extends Validate -{ - protected $rule = [ - 'id' => 'required|numeric', - 'content' => 'required|digits_between:1,2000', - 'title' => 'required|digits_between:4,50|alpha', - ]; - - protected $message = [ - 'id.required' => '缺少参数:文章Id', - 'id.numeric' => '参数错误:文章Id', - 'content.required' => '文章内容必须填写', - 'content.digits_between' => '文章长度为1~2000个字符', - 'title.required' => '文章标题必须填写', - 'title.digits_between' => '文章标题格式错误', - 'title.alpha' => '文章标题长度为4~50个字符', - ]; - - protected $scene = [ - 'add' => ['content','title'], - 'edit' => ['id','content','title'], - 'del' => ['id'], - ]; -} -``` -然后可以在验证方法中使用验证的场景,使用`scene`方法指定验证场景 -``` php -$data = [ - 'content' => '内容', - 'title' => '这是一个标题' -]; -$validate = new ArticleValidate(); -$data = $validate->scene('add')->check($data); -``` -## 验证场景复用 -有时候验证场景中的字段,要求都一样的时候,可以使用`use`关键词使用验证器 - -> 请注意:[规则管理器](https://v.neww7.com/3/RuleManager.html)不支持验证场景复用 -``` php -protected $scene = [ - 'edit' => ['id','content','title'], - 'save' => ['use' => 'edit'], -]; -``` -``` php -$validate = new ArticleValidate(); -$validate->scene('save')->check($data); -``` -这里是`save`场景,实际上是用的`edit`场景字段 ->
    如都定义了中间件,则都生效
    - - -`use`关键词也支持传入自定义方法 -``` php -protected $scene = [ - 'save' => ['type','use' = 'selectSaveScene'], - 'saveSetting' => ['id','name'] -] - - -protected function useSelectSaveScene(array $data) -{ - return 'save'.$data['type']; -} -``` - ->自定义方法的参数 -自定义方法会有一个数组类型的参数,传入的参数为第一次验证后的数据,也就是除去`use`字段的其他字段,返回字符串为使用对应的验证场景,返回数组为使用对应的验证字段 - -## 自定义验证场景 -可以单独为某个场景定义方法(方法的命名规范是`scene`+ 首字母大写的场景名),方法提供一个[场景类](https://v.neww7.com/3/Scene.html#场景类的方法),可用于对某些字段的规则重新设置,例如: - -- 在[规则管理器](https://v.neww7.com/3/RuleManager.html)中的场景类为:`W7\Validate\Support\RuleManagerScene` -- 在[验证器](https://v.neww7.com/3/Validate.html)中的场景类为:`W7\Validate\Support\ValidateScene` - -> 注意 -场景名在调用的时候不能将驼峰写法转为下划线 - - -``` php -protected function sceneEdit($scene) -{ - $scene->only(['id','content','title']) - ->append('id',"max") - ->remove("content",'between') - ->remove('title',null) - ->append('title','required|between|alpha'); -} -``` -> 说明 -`scene`验证场景在调用`check`方法以后会被重置,并不会对下一次`check`生效 - -## 验证字段为数组 -在验证器中,支持对数组下的元素进行定义规则,在验证场景中,同样支持指定验证数组元素 -规则的定义如下: -``` php -protected $rule = [ - 'search.order' => 'numeric|between:1,2', - 'search.keyword' => 'chsAlphaNum', - 'search.recycle' => 'boolean', -]; -``` -验证场景定义: -``` php -protected $scene = [ - 'list' => ['search.order','search.keyword','search.recycle'] -]; -``` -## 场景类的方法 -[验证器](https://v.neww7.com/3/Validate.html)的场景类方法说明如下: - -| 方法名 | 描述 | -| --- | --- | -| [only](https://v.neww7.com/3/Scene.html#only) | 场景中需要验证的字段 | -| [remove](https://v.neww7.com/3/Scene.html#remove) | 移除场景中的字段的部分验证规则 | -| [append](https://v.neww7.com/3/Scene.html#append) | 给场景中的字段追加验证规则 | -| [sometimes](https://v.neww7.com/3/Scene.html#sometimes) | 复杂条件验证| -| [event](https://v.neww7.com/3/Scene.html#event)|指定事件处理类| -| [getData](https://v.neww7.com/3/Scene.html#getdata)|获取当前验证的数据| -| [getValidateData](https://v.neww7.com/3/Scene.html#getvalidatedata)|作用同[getData](https://v.neww7.com/3/Scene.html#getdata),区别在于,此方法返回一个[验证器集合](https://v.neww7.com/3/Collection.html)类| -| [before](https://v.neww7.com/3/Scene.html#before)|添加一个验证前的需要执行的方法| -| [after](https://v.neww7.com/3/Scene.html#after)|添加一个验证后需要执行的方法| -| [appendCheckField](https://v.neww7.com/3/Scene.html#appendcheckfield)|添加一个需要验证的字段| -| [removeCheckField](https://v.neww7.com/3/Scene.html#removecheckfield)|删除一个需要验证的字段| -| [setEventPriority](https://v.neww7.com/3/Scene.html#seteventpriority)|设置事件和简易事件的优先级| -| [default](https://v.neww7.com/3/Scene.html#default)| 设置或取消一个字段的默认值| -| [filter](https://v.neww7.com/3/Scene.html#filter)|设置或取消一个字段的过滤器| - -[规则管理器](https://v.neww7.com/3/RuleManager.html)的场景类方法说明如下: - -| 方法名 | 描述 | -| --- | --- | -| [only](https://v.neww7.com/3/Scene.html#only) | 场景中需要验证的字段 | -| [remove](https://v.neww7.com/3/Scene.html#remove) | 移除场景中的字段的部分验证规则 | -| [append](https://v.neww7.com/3/Scene.html#append) | 给场景中的字段追加验证规则 | -| [appendCheckField](https://v.neww7.com/3/Scene.html#appendcheckfield)|添加一个需要验证的字段| -| [removeCheckField](https://v.neww7.com/3/Scene.html#removecheckfield)|删除一个需要验证的字段| - -### only -指定场景需要验证的字段 -```php -public function only(array $fields): $this -``` -- `$fields` 为要验证的字段数组 - -### remove -移除场景中的字段的部分验证规则 -``` php -public function remove(string $field, string $rule = null): $this -``` -- `$field` 为要移除规则的字段 -- `$rule` 为要移除的规则,多个规则用`|`分割,也可填入规则数组,`$rule`如为`null`,则清空该字段下的所有规则 - -### append -给场景中的字段需要追加验证规则 -``` php -public function append(string $field, string $rule): $this -``` -- `$field` 为要追加规则的字段 -- `$rule` 为要追加的规则,多个规则用`|`分割,也可填入规则数组 - -### sometimes -复杂条件验证 - -有时候你可能需要增加基于更复杂的条件逻辑的验证规则。例如,你可以希望某个指定字段在另一个字段的值超过 100 时才为必填。或者当某个指定字段存在时,另外两个字段才能具有给定的值 -``` php -public function sometimes($attribute, $rules, callable $callback): $this -``` -- `$attribute` 要追加规则的字段,多个可传数组 -- `$rules` 要追加的规则,多个规则用`|`分割,也可填入规则数组 -- `$callback` 闭包方法,如果其返回`true`, 则额外的规则就会被加入 -> 参数:传入 闭包 的`$data`参数是`W7\Validate\Support\Storage\ValidateCollection`的一个实例,可用来访问你的输入或文件对象。 - - -我们可以根据一个参数或多个来处理其他参数的验证条件,更灵活的实现验证: -``` php -$scene->sometimes("name","required",function ($data) { - return $data->type === 1; -}); -``` - -### event -指定[场景事件](https://v.neww7.com/3/Event.html)处理类,一个场景可以使用多个[场景事件](https://v.neww7.com/3/Event.html)处理类 -``` php -public function event(string $handler, ...$params): $this -``` -- `$handler` 处理器命名空间,可使用`:class`进行传入 -- `$params` 传递给中间件构建方法的参数,不限数量 -### getData -此方法用来获取当前验证的数据 -```php -public function getData(string $key = '', $default = null) -``` -默认获取全部验证的值 -### getValidateData -此方法用来获取当前验证的数据,作用同[getData](https://v.neww7.com/3/Scene.html#getdata),区别在于,此方法返回一个[验证器集合](https://v.neww7.com/3/Collection.html)类 -```php -public function getValidateData(): ValidateCollection -``` -### before -添加一个验证前的需要执行的方法,方法仅限本类的方法,方法的命名规则为`before`加方法名,方法的定义查看[简单使用](https://v.neww7.com/3/Event.html#简单使用) -```php -public function before(string $callbackName, ...$params): $this -``` -- `$callbackName` 本类的方法名,不带前缀 -- `$params` 要传递给方法的参数 -### after -添加一个验证后需要执行的方法,方法仅限本类的方法,方法的命名规则为`after`加方法名,方法的定义查看[简单使用](https://v.neww7.com/3/Event.html#简单使用) -```php -public function after(string $callbackName, ...$params): $this -``` -- `$callbackName` 本类的方法名,不带前缀 -- `$params` 要传递给方法的参数 -### appendCheckField -添加一个需要验证的字段,当需要根据Sql或者其他各种条件来增加一个需要验证的字段时,你就需要用到`appendCheckField`这个方法 -```php -public function appendCheckField(string $field): $this -``` -- `$field` 需要添加的字段名称 -### removeCheckField -删除一个需要验证的字段,当需要根据Sql或者其他各种条件来删除一个正在验证的字段时,你就需要用到`removeCheckField`这个方法 -```php -public function removeCheckField(string $field): $this -``` -- `$field` 需要删除的字段名称 -### setEventPriority -设置[事件](https://v.neww7.com/3/Event.html)和[简易事件](https://v.neww7.com/3/Event.html#简单使用)的优先级 -```php -public function setEventPriority(bool $priority): Validate -``` -- 当值为True时,执行顺序为:`事件类beforeValidate`->`简易事件before`->`开始数据验证`->`简易事件after`->`事件类afterValidate` -- 当值为False时,执行顺序为:`简易事件before`->`事件类beforeValidate`->`开始数据验证`->`事件类afterValidate`->`简易事件after` -### default -设置或取消一个字段的[默认值](https://v.neww7.com/3/Default.html) -```php -public function default(string $field, $callback, bool $any = false): $this -``` -- `$field` 字段名称 -- `$callback` 默认值或者匿名函数等,如果为`null`,则取消该字段的默认值 -- `$any` 是否处理任意值,默认只处理空值 -### filter -设置或取消一个字段的[过滤器](https://v.neww7.com/3/Filter.html) -```php -public function filter(string $field, $callback): $this -``` -- `$field` 字段名称 -- `$callback` 全局函数名,匿名函数,过滤器类或其他 - -# 自定义规则 -## 前置处理 -使用自定义验证规则之前,必须先定义自定义验证规则的命名空间前缀 -``` php -ValidateConfig::instance()->rulesPath('W7\\App\\Model\\Validate\\Rules\\'); -``` -建议在`Provider`中定义验证相关的设置 -## 使用规则对象 -验证器内有很多有用的验证规则;同时也支持自定义规则。注册自定义验证规则的方法之一,就是新建一个规则并继承`W7\Validate\Support\Rule\BaseRule`。新的规则存放在你[设置好的目录](https://v.neww7.com/3/Start.html#配置自定义规则类路径)中 - -一旦创建了规则,我们就可以定义它的行为。 `passes`方法接收属性值和名称,并根据属性值是否符合规则而返回`true`或`false`。 `message`属性为验证失败时使用的验证错误消息,此错误消息可被验证器中定义的`message`覆盖: - -``` php -namespace W7\App\Model\Validate\Rules; - -class Chs extends BaseRule -{ - /** - * 默认错误消息 - * @var string - */ - protected $message = ':attribute的值只能具有中文'; - - /** - * 确定验证规则是否通过。 - * - * @param mixed $attribute - * @param mixed $value - * @return bool - */ - public function passes($attribute, $value): bool - { - return is_scalar($value) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$value); - } -} -``` -一旦规则对象被定义好后,你可以通过将规则对象的实例和其他验证规则一起来传递给验证器: -``` php -protected $rule = [ - 'title' => 'required|chs', -]; -``` ->
    自定义扩展规则首字母可小写,也建议使用小写
    - -### 自定义规则传入参数 -自定义规则,和其他规则一样,也支持传入参数,类似于`max:100`,`in:0,1,2`此类,参数将按顺序传入自定义规则类中的构造函数中,如下: -```php {7} -class Length extends BaseRule -{ - protected $message = ':attribute的长度不符合要求'; - - protected $size; - - public function __construct(int $size) - { - $this->size = $size; - } - - public function passes($attribute, $value): bool - { - return strlen($value) === $this->size; - } -} - -``` - -### 格式化错误消息 -在[上诉代码](https://v.neww7.com/3/Rule.html#自定义规则传入参数)中,错误提示可能并不是那么清晰,将`$size`变量放入错误提示,也许会更好,我们提供了`$messageParam`参数,用于支持格式化错误消息,如下: -```php {10} -class Length extends BaseRule -{ - protected $message = ':attribute的长度需为%d个字节'; - - protected $size; - - public function __construct(int $size) - { - $this->size = $size; - $this->messageParam = [$size]; - } - - public function passes($attribute, $value): bool - { - return strlen($value) === $this->size; - } -} - -``` -`$messageParam`是一个数组类型,所以传入的值必须为数组,如使用规则为`length:10`,则触发后的消息为:`:attribute的长度需为10个字节` - -`$message`字段定义: - -| 格式化格式 | 说明 | -| --- | --- | -| %% | 返回一个百分号 %| -| %b | 二进制数| -| %c | ASCII 值对应的字符| -| %d | 包含正负号的十进制数(负数、0、正数)| -| %e | 使用小写的科学计数法(例如 1.2e+2)| -| %E | 使用大写的科学计数法(例如 1.2E+2)| -| %u | 不包含正负号的十进制数(大于等于 0)| -| %f | 浮点数(本地设置)| -| %F | 浮点数(非本地设置)| -| %g | 较短的 %e 和 %f| -| %G | 较短的 %E 和 %f| -| %o | 八进制数| -| %s | 字符串| -| %x | 十六进制数(小写字母)| -| %X | 十六进制数(大写字母)| - -附加的格式值。必需放置在 % 和字母之间(例如 %.2f): - -- `\+` (在数字前面加上 + 或 - 来定义数字的正负性。默认情况下,只有负数才做标记,正数不做标记) -- `'` (规定使用什么作为填充,默认是空格。它必须与宽度指定器一起使用。例如:%'x20s(使用 "x" 作为填充)) -- `\-` (左调整变量值) -- `[0-9]` (规定变量值的最小宽度) -- `.[0-9]` (规定小数位数或最大字符串长度) - -> 注意 如果使用多个上述的格式值,`$messageParam`的参数必须按照上面的顺序进行使用,不能打乱。 - -关于错误消息的更多支持请查看[自定义错误消息](https://v.neww7.com/3/Message.html) -## 使用扩展 -### extend 扩展方法 -注册自定义的验证规则的另一种方法是使用`Validate`中的 `extend `方法。让我们在[验证器](https://v.neww7.com/3/Validate.html)中使用这个方法来注册自定义验证规则: -``` php -public function __construct() -{ - self::extend("check_admin",function($attribute, $value, $parameters, $validator){ - return $value === "owner"; - }); -} -``` -自定义的验证闭包接收四个参数:要被验证的属性名称 `$attribute`、属性的值 `$value`、传入验证规则的参数数组 `$parameters` 、以及 `Validator` 实例。 -除了使用闭包,你也可以传入类和方法到`extend`方法中: -``` php -Validate::extend("check_admin","permissionValidate@checkAdmin"); -``` -> 请注意 -传入类和方法需要指定方法为`public`类型,类要传入完整的命名空间,如果你的方法为静态方法,还可以通过数组形式进行传入[完整类名,方法名],如方法名没有传,则默认方法名为`validate` - -### 使用类方法 -自定义规则也支持直接使用当前验证器类下的方法,规则为`rule` + 规则名,如`ruleCheckLogin` - -> 请注意 这里的`checkLogin`和当前验证器下的其他方法注册的规则名不能重复,否则会覆盖 - -自定义规则方法类方法接收四个参数:要被验证的属性名称 `$attribute`、属性的值 `$value`、传入验证规则的参数数组 `$parameters` 、以及 `Validator` 实例。 -```php -class LoginValidate extends Validate -{ - protected $rule = [ - 'user' => 'required|alphaNum|checkLogin' - ]; - - protected $message = [ - 'user.checkLogin' => '登录失败' - ]; - - public function ruleCheckLogin($attribute, $value, $parameters, $validator): bool - { - return 'admin' === $value; - } -} -``` -### replacer 错误信息替换器 -如果需要定义错误消息,可以在`extend`的第三个参数中填入,或通过`replacer`方法进行定义 -`replacer`方法接受两个参数`ruleName`和一个闭包参数,闭包接受四个参数:错误消息`$message`, 被验证的属性名称`$attribute`, 当前的规则名称`$rule`,传入验证规则的参数数组`$parameters` -```php -Validate::replacer("check_admin",function($message,$attribute,$rule,$parameters){ - return "自定义错误消息" -}); -``` -除了使用闭包以外,也支持传入类和方法到`replacer`方法中 -```php -Validate::replacer("check_admin","permissionValidate@checkAdminMessage"); -``` -> 请注意 -传入类和方法需要指定方法为`public`类型,类要传入完整的命名空间,不支持数组传递,如方法名没有传,则默认方法名为`replace` - -可以覆盖默认规则的自定义消息,如果要定义自定义方法的错误消息,一定要先定义错误规则`extend`,再定义错误消息`replacer` - - -使用方式同使用规则对象 -```php -protected $rule = [ - 'title' => 'required|chs|check_admin', -]; -``` -### extendImplicit 隐式扩展 -默认情况下,当所要验证的属性不存在或包含一个空字符串时,使用包含自定义扩展的正常的验证规则是不会执行的。例如,`unique` 规则将不会检验空字符串: -```php -$rules = ['name' => 'unique:users,name']; - -$input = ['name' => '']; - -// 验证通过 -``` -如果即使属性为空也要验证规则,则一定要暗示属性是必须的。要创建这样一个「隐式」扩展,可以使用 `Validate`中的`extendImplicit()` 方法: -```php -Validate::extendImplicit('foo', function ($attribute, $value, $parameters, $validator) { - return $value == 'foo'; -}); -``` ->
    注意:「隐式」扩展只暗示该属性是必需的。至于它到底是缺失还是空值这取决于你。
    - -### ImplicitRule 隐式规则对象 -如果你想要在属性为空时执行规则对象,你应该实现 `Illuminate\Contracts\Validation\ImplicitRule` 接口。这个接口将充当验证器的「标记接口」;因此,它不包含你要实现的任何方法。 -### extendDependent 依赖性验证器 -如果想定义一个自定义扩展对数组进行验证时,我们会发现`extend`和`extendImplicit`均不会解析`*`,这个时候就需要用到`Validate`中的`extendDependent`方法: -```php -Validate::extendDependent('contains', function ($attribute, $value, $parameters, $validator) { - // 下面验证器传来的$parameters是['*.provider'],当我们暗示这个自定义规则是依赖性的时候 - // 验证器往往会按照我们要验证的原始属性,用当前的指数替换星号,所以*.provider会被替换成0.provider - // 现在我们可以使用Arr:get()来获取其他字段的值。 - // 所以这个自定义规则验证了属性值包含了其他给定属性的值。 - return str_contains($value,Arr::get($validator->getData(),$parameters[0])); -}); - -$v = new Validate($request); -$v->setRules([ - '*.email' => 'contains:*.provider' -])->check([ - [ - 'email' => '995645888@qq.com', 'provider' => 'qq.com' - ] -]); -``` -# 规则管理器 -## 介绍 -对验证的规则进行管理,[验证器](https://v.neww7.com/3/Validate.html)是规则管理器的子类,如果你仅需要对规则进行管理,可直接继承该类。 -```php -class UserRulesManager extends RuleManager -{ - protected $rule = [ - 'user' => 'required|email', - 'pass' => 'required|lengthBetween:6,16', - 'name' => 'required|chs|lengthBetween:2,4', - 'remark' => 'required|alpha_dash', - 'captcha' => 'required|length:4|checkCaptcha', - ]; - - protected $scene = [ - 'login' => ['user', 'pass'], - 'captcha' => ['captcha'] - ]; - - protected $customAttributes = [ - 'user' => '用户名', - 'pass' => '密码', - 'name' => '昵称', - 'remark' => '备注', - 'captcha' => '验证码', - ]; - - protected $message = [ - 'captcha.checkCaptcha' => '验证码错误', - 'user.email' => '用户名必须为邮箱', - 'pass.lengthBetween' => '密码长度错误' - ]; - - protected function sceneRegister(RuleManagerScene $scene) - { - return $scene->only(['user', 'pass', 'name', 'remark']) - ->remove('remark', 'required|alpha_dash') - ->append('remark', 'chs'); - } - - protected function sceneRegisterNeedCaptcha(RuleManagerScene $scene) - { - return $this->sceneRegister($scene)->appendCheckField('captcha'); - } - - public function ruleCheckCaptcha($att, $value): bool - { - return true; - } -} -``` -> 提示 -在规则管理器中,可以使用[自定义规则](https://v.neww7.com/3/Rule.html)一节中提到的方式来扩展规则和错误消息 - - -## 获取规则 -可以直接调用类的静态方法`get`来获取规则、错误消息、属性名称 -```php -public static function get($fields = null, bool $initial = false): array -``` -- `$fields` 要获取的字段名称,如果为null,则获取所有规则 -- `$initial` 是否获取原始规则,默认为false,即解析后的规则 -```php -UserRulesManager::get('user'); -``` -> 请注意 -如果想应用验证场景的规则,请实例化类后使用`scene`方法指定验证场景后再调用`get`方法 - -```php -(new UserRulesManager())->scene('register')->get('user'); -``` -将返回 -```php -Array -( - [0] => Array - ( - [user] => Array - ( - [0] => required - [1] => email - ) - - ) - - [1] => Array - ( - [user.email] => 用户名必须为邮箱 - ) - - [2] => Array - ( - [user] => 用户名 - ) - -) -``` -获取指定[验证场景](https://v.neww7.com/3/Scene.html)下所有的规则、错误消息、属性名称,可直接使用`getBySceneName`静态方法: -```php -UserRulesManager::getBySceneName('register'); -``` -也可以直接调用静态方法 -```php -UserRulesManager::register(); -``` -## 单独获取 -如果想单独的获取规则,错误消息,属性名称,你可以实例化规则管理器后使用下列方法: - -- `getRules` 获取规则 -- `getCustomAttributes` 获取属性名称 -- `getMessages` 获取错误消息 - -> 请注意 -`getRules`方法受`scene`方法影响,不同的场景下取出的规则可能不同 - -# 自定义错误消息 -在[验证器](https://v.neww7.com/3/Validate.html)中提到使用`$message`参数来定义验证的错误消息,此节详细介绍错误消息的定义 - -## message变量 -错误消息`$message`变量支持填入 -- `:attribute` 表示字段名称 -- `{:field}` 表示字段内容 - -> 说明:上述文本在[自定义规则](https://v.neww7.com/3/Rule.html)中均支持使用 - -### :attribute -`:attribute` 代表为当前触发错误的`customAttributes`变量中的字段名称 -```php -class Test extends Validate -{ - protected $rule = [ - 'user' => 'required' - ]; - - protected $message = [ - 'user.required' => '请填写:attribute' - ]; - - protected $customAttributes = [ - 'user' => '账号' - ]; -} -``` - -触发后,提示的消息为`请填写账号` - -### {:field} -`{:field}`中间的`field`为当前验证值的字段,如果指定字段不存在,则为空文本,支持获取数组,如`info.name`,代表获取`info`数组中的`name`参数,可无限下层 -```php -class Test extends Validate -{ - protected $rule = [ - 'name' => 'chs' - ]; - - protected $message = [ - 'name.chs' => '你填写的名字{:name}不是中国名字' - ]; -} -``` -输入数据`['name' => 'Rasmus Lerdorf']`,提示:`你填写的名字Rasmus Lerdorf不是中国名字` - -## customAttributes变量 -当我们定义了大量的验证字段和规则时,如果一个一个对应的编写错误消息,需要耗费大量的时间成本,这个时候,我们可以使用`$customAttributes`变量定义字段的名称。 - -当错误触发时,会自动替换默认错误消息中的`:attribute`文本 - -```php {7-9} -class User extends Validate -{ - protected $rule = [ - 'id' => 'required|numeric', - ]; - - protected $customAttributes = [ - 'id' => '字段ID', - ]; -} -``` -当错误触发时,会提示`字段ID 不可为空`,`字段ID 必须为数字` -customAttributes变量中也支持`{:field}`,如: -```php {2} -protected $customAttributes = [ - 'id' => '字段ID:{:id}', -]; -``` -如果传入`id`为`hello` - -此时触发后会提示`字段ID:hello 必须为数字` - -# 过滤器 -在验证后给输入值应用一个过滤器, 并在验证后把它赋值回原属性变量。 - -## 说明 -过滤器可以为全局函数名,匿名函数,过滤器类或其他,该函数的样式必须是: -```php -function ($value) { - return $newValue; -} -``` -有许多的PHP方法结构和`filter`需要的结构一致。 比如使用类型转换方法 (`intval`, `boolval`, ...) 来确保属性为指定的类型, 你可以简单的设置这些方法名而不是重新定义一个匿名函数 -## 使用 -### 类属性定义 -```php -class UserValidate extends Validate -{ - protected $rule = [ - 'id' => 'required|array', - 'id.*' => 'numeric' - ]; - - protected $filter = [ - 'id.*' => 'intval' - ]; -} - -$data = UserValidate::make()->check([ - 'id' => ['1', 2] -]); -var_dump($data); -``` -输出 -``` -array(1) { - 'id' => - array(4) { - [0] => - int(1) - [1] => - int(2) - } -} -``` -### 在验证场景中使用 -```php -class UserValidate extends Validate -{ - protected $rule = [ - 'id' => 'required|array', - 'id.*' => 'numeric' - ]; - - protected function sceneToInt(ValidateScene $scene) - { - $scene->only(['id', 'id.*']) - ->filter('id.*', 'intval'); - } -} - -$data = UserValidate::make()->scene('toInt')->check([ - 'id' => ['1', 2] -]); -var_dump($data); -``` -输出 -``` -array(1) { - 'id' => - array(2) { - [0] => - int(1) - [1] => - int(2) - } -} -``` -## 过滤器类 -创建一个过滤器类,需要实现`W7\Validate\Support\Concerns\FilterInterface`接口: -```php -class UniqueFilter implements FilterInterface -{ - public function handle($value) - { - return array_unique($value); - } -} - -class UserValidate extends Validate -{ - protected $rule = [ - 'id' => 'required|array', - 'id.*' => 'numeric' - ]; - - protected $filter = [ - 'id' => UniqueFilter::class - ]; -} - -$data = UserValidate::make()->scene('toInt')->check([ - 'id' => [1,2,1,2,3,3,4] -]); -var_dump($data); -``` -输出 -``` -array(1) { - 'id' => - array(4) { - [0] => - int(1) - [1] => - int(2) - [4] => - int(3) - [6] => - int(4) - } -} -``` -## 类方法 -过滤器也支持直接写入类方法的方式,(方法的命名规范是`filter`+ 首字母大写的名称) -```php -class UserValidate extends Validate -{ - protected $rule = [ - 'id' => 'required|array', - 'id.*' => 'numeric' - ]; - - protected $filter = [ - 'id' => 'uniqueFilter' - ]; - - public function filterUniqueFilter($value) - { - return array_unique($value); - } -} -``` -在验证场景中可以直接使用`[$this,'filterUniqueFilter']`来传递`callable` -# 默认值 -为空值分配默认值,在验证之前执行,当值为空数组,空字符以及`null`时判断为空。 - -> 请注意 -默认值不支持数组元素,也就是说:为`id.*`这种设定默认值是不支持的 - -## 使用 -### 类属性定义 -使用类的`$default`参数来为字段设定默认值 -```php {8-11} -class Setting extends Validate -{ - protected $rule = [ - 'site_status' => 'required|in:0,1', - 'register_status' => 'required|in:0,1' - ]; - - protected $default = [ - 'site_status' => 1, - 'register_status' => 1 - ]; -} - -$data = Setting::make()->check([]); -print_r($data); -//Array -//( -// [site_status] => 1 -// [register_status] => 1 -//) -``` -### 在验证场景中使用 -在类中增加一个`base`验证场景 -```php -class Setting extends Validate -{ - protected $rule = [ - 'site_status' => 'required|in:0,1', - 'register_status' => 'required|in:0,1' - ]; - - protected $default = [ - 'site_status' => 1, - 'register_status' => 1 - ]; - - protected function sceneBase(ValidateScene $scene) - { - $scene->only(['site_status']) - ->default('site_status', 0); - } -} -$data = Setting::make()->scene('base')->check([]); -print_r($data); -//Array -//( -// [site_status] => 1 -//) -``` -> 说明 -一个字段只能拥有一个默认值,验证场景中的默认值生效后,全局定义的默认值就失效。 - -默认值只对当前需要验证的字段生效 - -## 多样的默认值 -### 闭包 -默认值支持闭包,闭包将收到三个值 -- `$value` 当前的值 -- `$attribute` 当前的字段名 -- `$originalData` 当前正在进行验证的全部原始数据 - -回调方法的样式如下: -```php -function($value, string $attribute, array $originalData) { - return $value; -} -``` -示例: -```php -$scene->defalt('name', function($value) { - return '张三'; -}); -``` -### 类方法 -使用类方法为指定字段传递默认值时,同样会接受到三个值 -- `$value` 当前的值 -- `$attribute` 当前的字段名 -- `$originalData` 当前正在进行验证的全部原始数据 - -```php -$scene->defalt('name', [$this,'setDefaultName']); - -public function setDefaultName($value, string $attribute, array $originalData) -{ - return '张三'; -} -``` -简易方法: - -定义一个默认值方法,(方法的命名规范是`default`+ 首字母大写的名称) -```php -$scene->defalt('name','setDefaultName'); - -public function defaultSetDefaultName($value, string $attribute, array $originalData) -{ - return '张三'; -} -``` -### 忽略空条件 -当值为空数组,空字符以及`null`时,才会取出对应默认值并赋值到原数据上, -如果你想任何值都获取一次默认值,可以增加`any => true`的条件,如果增加了`any`,你需要将你的默认值放入`value`中,如下: -```php -class Setting extends Validate -{ - protected $rule = [ - 'site_status' => 'required|in:0,1', - ]; - - protected $default = [ - 'site_status' => ['value' => 1, 'any' => true], - ]; -} -``` -这个时候,无论`site_status`的原始参数是什么,都会被重置为`1`,你也可以使用该特性,为参数做提前格式化等操作 -### 取消默认值 -如果你想在验证场景中,取消[类属性中](https://v.neww7.com/3/Default.html#类属性定义)设定的默认值,可以将值设定为`null`,如下: -```php -class User extends Validate -{ - protected $rule = [ - 'name' => '' - ]; - - protected $default = [ - 'name' => '张三' - ]; - - protected function sceneTest(ValidateScene $scene) - { - $scene->only(['name']) - ->default('name', null); - } -} - -$data = User::make()->scene('test')->check([]); // 返回空数组 -``` -### 提供默认值的类 -创建一个提供默认值的类,需要实现`W7\Validate\Support\Concerns\DefaultInterface`接口: -```php -class DefaultUserId implements DefaultInterface -{ - public function handle($value, string $attribute, array $originalData) - { - return $_SESSION['user_id']; - } -} -``` -使用: -```php -class UserValidate extends Validate -{ - protected $rule = [ - 'id' => 'required', - ]; - - protected $default = [ - 'id' => DefaultUserId::class - ]; -} -``` -# 验证事件 -## 验证事件处理 -目前支持的验证事件为 -- 验证前事件`beforeValidate` -- 验证后事件`afterValidate` - ->
    事件仅支持在场景中定义使用
    - -验证器中间件需要继承`W7\Validate\Support\Event\ValidateEventAbstract` - -事件类拥有三个类属性 - -- `$sceneName` 当前的场景名称 -- `$data` 验证前的值或验证后的值 -- `$message` 错误消息,如果事件返回`false`,则验证器将取此值作为错误消息 - -```php -abstract class ValidateEventAbstract implements ValidateEventInterface -{ - public function beforeValidate(): bool; - public function afterValidate(): bool; -} -``` - -场景事件处理类构建函数中可以取到传递过来的值 - -如场景中使用了`event(CheckPermission::class,1,2,3)`,则构建函数 -```php -public function __construct($a,$b,$c) -{ - -} -``` -可依次获取到`$a = 1` `$b = 2` `$c = 3` - -## 使用方法 -### 在验证场景中 -可在验证场景中使用`event`关键词 - -如果不需要给场景事件处理类传值: -``` php -protected $scene = [ - 'add' => ['id','user_id','role','event' => CheckPermission::class], -]; -``` -如果需要给场景事件处理类传值: -``` php -protected $scene = [ - 'add' => ['id','user_id','role','event' => [ - CheckPermission::class=>[1,2,3,4] - ]], -]; -``` - ->
    传值的数量不限制,可在场景事件处理类的构建函数中获取
    - -### 在自定义验证场景中 -在自定义验证场景中,可使用`event`方法定义要使用的场景事件处理类,不限数量 -```php -/* -* @method $this event(string $handler,...$params) -*/ - -$scene->event(CheckPermission::class) -``` -如果要传值 -``` php -$scene->event(CheckPermission::class,1,2,3) -``` -使用多个场景事件处理类 -```php -$scene->event(CheckPermission::class,1,2,3)->event(CheckName::class) -``` -## 全局事件处理器 -如果你某个验证器中的所有场景都使用到共同的事件处理器,可以定义一个全局的事件处理器 -```php -protected $event = [ - CheckPermission::class => ['owner'] -]; -``` -可定义多个全局事件处理器,如果场景中也定义了事件处理器,则全部生效 - -## 简单使用 -如果你只是想在验证前给某个字段设置一个默认值或在每个字段验证后进行一个总的验证等需求,而此验证业务不需要复用, -可以直接`after`和`before`来进行简单定义。而不需要去定义一个类 - -在自定义验证场景中,可使用`after`和`before`方法定义要使用的事件处理方法,不限数量 -- `before` 在验证之前执行的方法 -- `after` 在验证之后执行的方法 - -方法接受一个验证数据`array $data`参数 - -与事件类`event`同用时的执行顺序为:`beforeValidate`->`before`->`after`->`afterValidate` - -> 如果想更改执行顺序,可以在[自定义验证场景](https://v.neww7.com/3/Scene.html#自定义验证场景)中使用[setEventPriority](https://v.neww7.com/3/Scene.html#seteventpriority)方法 - -方法仅限本类的方法,方法的命名规则为`after`或`before`加方法名,如: -```php -class LoginValidate extends \W7\Validate\Validate -{ - protected $rule = [ - 'name' => 'required|chs', - 'user' => 'required|alpha_dash', - 'pass' => 'required|min:8', - ]; - - protected $scene = [ - 'register' => ['name', 'user', 'pass', 'before' => 'checkRegisterStatus'] - ]; - - public function beforeCheckRegisterStatus(array $data) - { - return true; - } -} -``` -简单使用也可以为方法传递参数,传参方法同[使用方法](https://v.neww7.com/3/Event.html#使用方法),只不过要将类名换为方法名,第一个参数为当前验证的值或者验证后的值 -```php -protected $message = [ - 'user.required' => '用户名不可为空' -]; - -protected $scene = [ - 'register' => ['name', 'user', 'pass', 'before' => 'setDefaultName','after'=> [ - 'checkUserExist' => [1,2,3,4] - ]] -]; - -public function afterCheckUserExist(array $data,$a,$b,$c) -{ - return true; -} -``` -同样可依次获取到`$a = 1` `$b = 2` `$c = 3` - -> 返回值: -> 如果返回的是字符串,则抛出`W7\Validate\Exception\ValidateException`异常,代表未通过,如果通过,则返回`$next($data);` -> -> 事件中可以直接返回`message`的`key`值,如`user.required`,验证器会自动查找对应的错误消息。 - -# 自定义错误消息 -在[验证器](https://v.neww7.com/3/Validate.html)中提到使用`$message`参数来定义验证的错误消息,此节详细介绍错误消息的定义 - -## message变量 -错误消息`$message`变量支持填入 -- `:attribute` 表示字段名称 -- `{:field}` 表示字段内容 - -> 说明:上述文本在[自定义规则](https://v.neww7.com/3/Rule.html)中均支持使用 - -### :attribute -`:attribute` 代表为当前触发错误的`customAttributes`变量中的字段名称 -```php -class Test extends Validate -{ - protected $rule = [ - 'user' => 'required' - ]; - - protected $message = [ - 'user.required' => '请填写:attribute' - ]; - - protected $customAttributes = [ - 'user' => '账号' - ]; -} -``` - -触发后,提示的消息为`请填写账号` - -### {:field} -`{:field}`中间的`field`为当前验证值的字段,如果指定字段不存在,则为空文本,支持获取数组,如`info.name`,代表获取`info`数组中的`name`参数,可无限下层 -```php -class Test extends Validate -{ - protected $rule = [ - 'name' => 'chs' - ]; - - protected $message = [ - 'name.chs' => '你填写的名字{:name}不是中国名字' - ]; -} -``` -输入数据`['name' => 'Rasmus Lerdorf']`,提示:`你填写的名字Rasmus Lerdorf不是中国名字` - -## customAttributes变量 -当我们定义了大量的验证字段和规则时,如果一个一个对应的编写错误消息,需要耗费大量的时间成本,这个时候,我们可以使用`$customAttributes`变量定义字段的名称。 - -当错误触发时,会自动替换默认错误消息中的`:attribute`文本 - -```php {7-9} -class User extends Validate -{ - protected $rule = [ - 'id' => 'required|numeric', - ]; - - protected $customAttributes = [ - 'id' => '字段ID', - ]; -} -``` -当错误触发时,会提示`字段ID 不可为空`,`字段ID 必须为数字` -customAttributes变量中也支持`{:field}`,如: -```php {2} -protected $customAttributes = [ - 'id' => '字段ID:{:id}', -]; -``` -如果传入`id`为`hello` - -此时触发后会提示`字段ID:hello 必须为数字` -- Gitee From 58bace4be1f6b8bdb05a2eb33dfd9438a370794c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9F=8E=E4=B8=AD=E9=81=93=E5=A3=AB?= Date: Thu, 17 Jun 2021 08:02:41 +0000 Subject: [PATCH 100/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=AA=8C=E8=AF=81=E5=AD=97=E6=AE=B5=E6=97=B6=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF=20!3=20*=20[fix]=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=AA=8C=E8=AF=81=E5=AD=97=E6=AE=B5=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/RuleManagerScene.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php index f680450..fb05760 100644 --- a/src/Support/RuleManagerScene.php +++ b/src/Support/RuleManagerScene.php @@ -103,7 +103,7 @@ class RuleManagerScene implements SceneInterface /** @inheritDoc */ public function appendCheckField(string $field): SceneInterface { - $rule = $this->rule[$field] ?? ''; + $rule = $this->checkRules[$field] ?? ''; $this->checkRules = array_merge($this->checkRules, [$field => $rule]); return $this; } -- Gitee From 0e61bc3f1efc784340027a85ab38525c6dfbb231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E4=BB=B2=E8=88=92?= Date: Thu, 17 Jun 2021 10:42:07 +0000 Subject: [PATCH 101/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DLinux=E4=B8=8Br?= =?UTF-8?q?un-script=20test=E6=97=A0=E6=B3=95=E6=89=A7=E8=A1=8C=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95=E7=9A=84=E9=97=AE=E9=A2=98=20!4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- phpunit.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml b/phpunit.xml index 9957e07..bcebe84 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,7 +1,7 @@ - tests\Test + tests/Test \ No newline at end of file -- Gitee From dba4343b1dce1fa97e86d23305de9618d6a3e104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 18 Jun 2021 11:13:54 +0800 Subject: [PATCH 102/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0Laravel?= =?UTF-8?q?=E5=92=8CRangine=E6=A1=86=E6=9E=B6=E7=9A=84Provider=E6=96=87?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E4=BD=BF=E5=85=B6=E4=B8=8D=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E6=8C=87=E5=AE=9A=E6=A1=86=E6=9E=B6=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 18 ++++++++++++-- src/Providers/Laravel/ValidateProvider.php | 24 ++++++++++++++++++ src/Providers/Rangine/ValidateProvider.php | 29 ++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 src/Providers/Laravel/ValidateProvider.php create mode 100644 src/Providers/Rangine/ValidateProvider.php diff --git a/composer.json b/composer.json index 84dea01..accc636 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "w7/engine-validate", - "description": "新版微擎表单验证", + "description": "增强表单验证", "license": "Apache-2.0", "authors": [ { @@ -13,7 +13,9 @@ }, "keywords": [ "w7", - "validate" + "validate", + "validator", + "form validate" ], "require": { "php": "^7.2.5|^8.0", @@ -36,5 +38,17 @@ "psr-4": { "W7\\Tests\\" : "tests/" } + }, + "extra": { + "rangine": { + "providers": [ + "W7\\Validate\\Providers\\Rangine\\ValidateProvider" + ] + }, + "laravel": { + "providers": [ + "W7\\Validate\\Providers\\Laravel\\ValidateProvider" + ] + } } } diff --git a/src/Providers/Laravel/ValidateProvider.php b/src/Providers/Laravel/ValidateProvider.php new file mode 100644 index 0000000..24d886c --- /dev/null +++ b/src/Providers/Laravel/ValidateProvider.php @@ -0,0 +1,24 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Providers\Laravel; + +use Illuminate\Support\ServiceProvider; +use W7\Validate\Support\Storage\ValidateConfig; + +class ValidateProvider extends ServiceProvider +{ + public function register() + { + ValidateConfig::instance()->setFramework(1); + } +} diff --git a/src/Providers/Rangine/ValidateProvider.php b/src/Providers/Rangine/ValidateProvider.php new file mode 100644 index 0000000..b24d9b2 --- /dev/null +++ b/src/Providers/Rangine/ValidateProvider.php @@ -0,0 +1,29 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Providers\Rangine; + +use W7\Core\Provider\ProviderAbstract; +use W7\Validate\Support\Storage\ValidateConfig; + +class ValidateProvider extends ProviderAbstract +{ + /** + * Register any application services. + * + * @return void + */ + public function register() + { + ValidateConfig::instance()->setFramework(2); + } +} -- Gitee From b5f06acdfbee2cc95b9f8ef5a2658fdbbb57d3b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8A=E9=9B=A8?= Date: Wed, 23 Jun 2021 11:35:08 +0000 Subject: [PATCH 103/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=9C=BA=E6=99=AF=E4=B8=AD=E6=97=A0=E6=B3=95=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=88=B0=E5=BD=93=E5=89=8D=E7=9A=84=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=80=BC=20!5=20*=20=E5=A2=9E=E5=8A=A0=E9=92=88=E5=AF=B9?= =?UTF-8?q?=E6=9C=AC=E6=AC=A1BUG=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=20*=20=E4=BF=AE=E5=A4=8D=E9=AA=8C=E8=AF=81=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E4=B8=AD=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96=E5=88=B0?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E7=9A=84=E9=AA=8C=E8=AF=81=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 2 +- tests/Test/TestBug.php | 44 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 tests/Test/TestBug.php diff --git a/src/Validate.php b/src/Validate.php index b84a1d8..ac3f0e6 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -213,7 +213,7 @@ class Validate extends RuleManager } if (method_exists($this, 'scene' . ucfirst($sceneName))) { - $scene = new ValidateScene($this->rule); + $scene = new ValidateScene($this->rule, $this->checkData); call_user_func([$this, 'scene' . ucfirst($sceneName)], $scene); $this->event = array_merge($this->event, $scene->events); $this->afters = array_merge($this->afters, $scene->afters); diff --git a/tests/Test/TestBug.php b/tests/Test/TestBug.php new file mode 100644 index 0000000..710b530 --- /dev/null +++ b/tests/Test/TestBug.php @@ -0,0 +1,44 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Support\ValidateScene; +use W7\Validate\Validate; + +class TestBug extends BaseTestValidate +{ + public function testBug5() + { + $v = new class extends Validate { + public $checkData = []; + + protected $rule = [ + 'name' => 'required' + ]; + + protected function sceneTest(ValidateScene $scene) + { + $this->checkData = $scene->getData(); + $scene->only(['name']); + } + }; + + $v->scene('test')->check([ + 'name' => 123 + ]); + + $this->assertArrayHasKey('name', $v->checkData); + $this->assertEquals(123, $v->checkData['name']); + } +} -- Gitee From 8f7713b697e9412eb88b18403e9bd2dbe2f10481 Mon Sep 17 00:00:00 2001 From: Blake-xu <9218664+Blake-xuhyy@user.noreply.gitee.com> Date: Thu, 24 Jun 2021 03:27:09 +0000 Subject: [PATCH 104/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DappendCheckFiel?= =?UTF-8?q?d=E4=B8=8D=E4=BC=9A=E5=A2=9E=E5=8A=A0=E5=8E=9F=E8=A7=84?= =?UTF-8?q?=E5=88=99=E7=9A=84=E9=97=AE=E9=A2=98=20!6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/RuleManagerScene.php | 16 ++++++---- src/Support/ValidateScene.php | 6 ++-- tests/Test/TestBug.php | 50 ++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php index fb05760..a15a6f0 100644 --- a/src/Support/RuleManagerScene.php +++ b/src/Support/RuleManagerScene.php @@ -22,19 +22,25 @@ class RuleManagerScene implements SceneInterface */ protected $checkRules; + /** + * All original validation rules + * @var array + */ + protected $rules = []; + /** * RuleManagerScene constructor. - * @param array $checkRules The rules to be applied to the data. + * @param array $rules All original validation rules */ - public function __construct(array $checkRules = []) + public function __construct(array $rules = []) { - $this->checkRules = $checkRules; + $this->rules = $rules; } /** @inheritDoc */ public function only(array $fields): SceneInterface { - $this->checkRules = array_intersect_key($this->checkRules, array_flip($fields)); + $this->checkRules = array_intersect_key($this->rules, array_flip($fields)); return $this; } @@ -103,7 +109,7 @@ class RuleManagerScene implements SceneInterface /** @inheritDoc */ public function appendCheckField(string $field): SceneInterface { - $rule = $this->checkRules[$field] ?? ''; + $rule = $this->rules[$field] ?? ''; $this->checkRules = array_merge($this->checkRules, [$field => $rule]); return $this; } diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 669d20b..1910929 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -77,12 +77,12 @@ class ValidateScene extends RuleManagerScene /** * ValidateScene constructor. - * @param array $checkRules + * @param array $rules * @param array $checkData */ - public function __construct(array $checkRules = [], array $checkData = []) + public function __construct(array $rules = [], array $checkData = []) { - parent::__construct($checkRules); + parent::__construct($rules); $this->checkData = $checkData; } diff --git a/tests/Test/TestBug.php b/tests/Test/TestBug.php index 710b530..127ceb1 100644 --- a/tests/Test/TestBug.php +++ b/tests/Test/TestBug.php @@ -13,6 +13,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Exception\ValidateException; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; @@ -41,4 +42,53 @@ class TestBug extends BaseTestValidate $this->assertArrayHasKey('name', $v->checkData); $this->assertEquals(123, $v->checkData['name']); } + + public function testBug6() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'required', + 'b' => 'required', + 'c' => 'required', + ]; + + protected $message = [ + 'a.required' => 'a不能为空', + 'b.required' => 'b不能为空', + 'c.required' => 'c不能为空', + ]; + + protected function sceneTest(ValidateScene $scene) + { + $scene->only(['a']) + ->appendCheckField('b') + ->appendCheckField('c'); + } + }; + + try { + $v->scene('test')->check([ + 'a' => 1 + ]); + } catch (ValidateException $e) { + $this->assertEquals('b不能为空', $e->getMessage()); + } + + try { + $v->scene('test')->check([ + 'a' => 1, + 'b' => 1 + ]); + } catch (ValidateException $e) { + $this->assertEquals('c不能为空', $e->getMessage()); + } + + $data = $v->scene('test')->check([ + 'a' => 1, + 'b' => 1, + 'c' => 1, + ]); + + $this->assertEmpty(array_diff_key($data, array_flip(['a', 'b', 'c']))); + } } -- Gitee From 7803bb147416695d003edcf2500c0ab825645ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 24 Jun 2021 11:38:59 +0800 Subject: [PATCH 105/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=99=A8=E7=9A=84use=E5=85=B3=E9=94=AE=E8=AF=8D?= =?UTF-8?q?=E4=B8=BAnext=20[U]=20=E4=BF=AE=E6=94=B9=E4=BD=BF=E7=94=A8next?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E4=B8=8B=E4=B8=80=E4=B8=AA=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E5=90=8E=EF=BC=8C=E9=AA=8C=E8=AF=81=E5=90=8E=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=B0=86=E5=85=A8=E9=83=A8=E7=B4=AF=E5=8A=A0=20[U]=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9C=BA=E6=99=AF=E9=80=89=E6=8B=A9=E5=99=A8?= =?UTF-8?q?=E7=9A=84=E5=91=BD=E5=90=8D=E8=A7=84=E5=88=99=E4=B8=BA=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E5=99=A8=E5=90=8D=E7=A7=B0+Selector=20[D]=20=E5=88=A0?= =?UTF-8?q?=E9=99=A4setFramework=E6=96=B9=E6=B3=95=EF=BC=8C=E5=A6=82?= =?UTF-8?q?=E4=B8=BA=E8=BD=AF=E6=93=8E=E5=92=8CLaravel=E6=A1=86=E6=9E=B6?= =?UTF-8?q?=EF=BC=8C=E6=89=A9=E5=B1=95=E4=BC=9A=E8=87=AA=E5=8A=A8=E5=88=A4?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Providers/Laravel/ValidateProvider.php | 2 +- src/Providers/Rangine/ValidateProvider.php | 3 +- src/RuleManager.php | 12 ++- src/Support/Storage/ValidateConfig.php | 39 +--------- src/Support/ValidateScene.php | 18 ++--- src/Validate.php | 62 +++++++++------- tests/Material/ArticleValidate.php | 2 +- .../Test/{TestBug.php => Fixer/TestScene.php} | 17 ++++- tests/Test/TestValidateSceneUse.php | 74 +++++++++++++++++++ 9 files changed, 149 insertions(+), 80 deletions(-) rename tests/Test/{TestBug.php => Fixer/TestScene.php} (82%) create mode 100644 tests/Test/TestValidateSceneUse.php diff --git a/src/Providers/Laravel/ValidateProvider.php b/src/Providers/Laravel/ValidateProvider.php index 24d886c..69647b7 100644 --- a/src/Providers/Laravel/ValidateProvider.php +++ b/src/Providers/Laravel/ValidateProvider.php @@ -19,6 +19,6 @@ class ValidateProvider extends ServiceProvider { public function register() { - ValidateConfig::instance()->setFramework(1); + ValidateConfig::instance()->setFactory(App::make('validator')); } } diff --git a/src/Providers/Rangine/ValidateProvider.php b/src/Providers/Rangine/ValidateProvider.php index b24d9b2..4a0e699 100644 --- a/src/Providers/Rangine/ValidateProvider.php +++ b/src/Providers/Rangine/ValidateProvider.php @@ -13,6 +13,7 @@ namespace W7\Validate\Providers\Rangine; use W7\Core\Provider\ProviderAbstract; +use W7\Facade\Container; use W7\Validate\Support\Storage\ValidateConfig; class ValidateProvider extends ProviderAbstract @@ -24,6 +25,6 @@ class ValidateProvider extends ProviderAbstract */ public function register() { - ValidateConfig::instance()->setFramework(2); + ValidateConfig::instance()->setFactory(Container::get("W7\Contract\Validation\ValidatorFactoryInterface")); } } diff --git a/src/RuleManager.php b/src/RuleManager.php index 3c4e096..bc97743 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -161,15 +161,25 @@ class RuleManager */ private function getRuleClass(string $ruleName) { + static $rulesClass = []; + list($ruleName, $param) = Common::getKeyAndParam($ruleName, true); foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { $ruleNameSpace = $rulesPath . ucfirst($ruleName); - if (class_exists($ruleNameSpace) && is_subclass_of($ruleNameSpace, BaseRule::class)) { + if (isset($rulesClass[$ruleNameSpace])) { + if (0 === $rulesClass[$ruleNameSpace]) { + continue; + } else { + return new $ruleNameSpace(...$param); + } + } elseif (class_exists($ruleNameSpace) && is_subclass_of($ruleNameSpace, BaseRule::class)) { + $rulesClass[$ruleNameSpace] = 1; return new $ruleNameSpace(...$param); } } + $rulesClass[$ruleName] = 0; return false; } diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 3cd7e1e..3f1c62a 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -16,12 +16,10 @@ use Composer\Autoload\ClassLoader; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Translation\Translator; use Illuminate\Filesystem\Filesystem; -use Illuminate\Support\Facades\App; use Illuminate\Translation\FileLoader; use Illuminate\Validation\Factory; use Illuminate\Validation\PresenceVerifierInterface; use ReflectionClass; -use RuntimeException; final class ValidateConfig { @@ -55,13 +53,6 @@ final class ValidateConfig */ protected $verifier; - /** - * Frame Type - * 1 Laravel 2 Rangine - * @var int - */ - protected $framework = 0; - protected static $instance; public static function instance(): ValidateConfig @@ -73,17 +64,6 @@ final class ValidateConfig return self::$instance; } - /** - * Set the frame type - * - * @param int $type 1 Laravel 2 Rangine - */ - public function setFramework(int $type): ValidateConfig - { - $this->framework = $type; - return $this; - } - /** * Provide validator factory * @@ -104,22 +84,9 @@ final class ValidateConfig public function getFactory(): Factory { if (empty($this->factory)) { - if ($this->framework > 0) { - switch ($this->framework) { - case 1: - $this->factory = App::make('validator'); - break; - case 2: - $this->factory = \W7\Facade\Container::get("W7\Contract\Validation\ValidatorFactoryInterface"); - break; - default: - throw new RuntimeException('Framework Type Error'); - } - } else { - $this->factory = new Factory($this->getTranslator(), $this->getContainer()); - if ($this->getPresenceVerifier()) { - $this->factory->setPresenceVerifier($this->getPresenceVerifier()); - } + $this->factory = new Factory($this->getTranslator(), $this->getContainer()); + if ($this->getPresenceVerifier()) { + $this->factory->setPresenceVerifier($this->getPresenceVerifier()); } } diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 1910929..6054357 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -86,15 +86,6 @@ class ValidateScene extends RuleManagerScene $this->checkData = $checkData; } - public function __get($name) - { - if (property_exists($this, $name)) { - return $this->$name; - } - - throw new RuntimeException('Unknown property:' . $name); - } - /** * Add conditions to a given field based on a Closure. * @@ -271,4 +262,13 @@ class ValidateScene extends RuleManagerScene { return validate_collect($this->getData()); } + + public function __get($name) + { + if (property_exists($this, $name)) { + return $this->$name; + } + + throw new RuntimeException('Unknown property:' . $name); + } } diff --git a/src/Validate.php b/src/Validate.php index ac3f0e6..48e7840 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -109,6 +109,10 @@ class Validate extends RuleManager */ private $checkData = []; + private $validatedData = []; + + private $validateFields = []; + /** * Create a validator * @@ -149,7 +153,7 @@ class Validate extends RuleManager $this->checkData = $data; $this->addEvent($this->event); $rule = $this->getCheckRules($this->getInitialRules()); - $fields = array_keys($rule); + $fields = array_merge(array_keys($rule), $this->validateFields); $this->defaults = array_merge($this->default, $this->defaults); $this->filters = array_merge($this->filter, $this->filters); $data = $this->handleDefault($data, $fields); @@ -171,6 +175,7 @@ class Validate extends RuleManager } $data = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes)->validate(); + $data = array_merge($this->validatedData, $data); $data = $this->handlerFilter($data, $fields); if ($this->eventPriority) { @@ -248,30 +253,31 @@ class Validate extends RuleManager unset($sceneRule['after']); } - // Determine if other authentication scenarios are specified for the authentication scenario - if (isset($sceneRule['use']) && !empty($sceneRule['use'])) { - $use = $sceneRule['use']; - if ($use === $sceneName) { + if (isset($sceneRule['next']) && !empty($sceneRule['next'])) { + $next = $sceneRule['next']; + if ($next === $sceneName) { throw new LogicException('The scene used cannot be the same as the current scene.'); } - unset($sceneRule['use']); - // If the specified `use` is a method - if (method_exists($this, 'use' . ucfirst($use))) { - // Pre-validation, where the values to be passed to the closure are validated according to the specified rules - $data = []; - if (!empty($sceneRule)) { - $randScene = md5(rand(1, 1000000) . time()); - $data = (clone $this)->setScene( - [$randScene => $sceneRule] - )->scene($randScene)->check($this->checkData); - } + unset($sceneRule['next']); + + // Pre-validation + if (!empty($sceneRule)) { + // Validated fields are not re-validated + $checkFields = array_diff($sceneRule, $this->validateFields); + $checkRules = $this->getCheckRules(array_intersect_key($this->rule, array_flip($checkFields))); + $data = $this->getValidationFactory()->make($this->checkData, $checkRules, $this->message, $this->customAttributes)->validate(); + $this->validateFields = array_merge($this->validateFields, $checkFields); + $this->validatedData = array_merge($this->validatedData, $data); + } - $use = call_user_func([$this, 'use' . ucfirst($use)], $data); - if (is_array($use)) { - return array_intersect_key($this->rule, array_flip($use)); + // If a scene selector exists + if (method_exists($this, lcfirst($next) . 'Selector')) { + $next = call_user_func([$this, lcfirst($next) . 'Selector'], $this->validatedData); + if (is_array($next)) { + return array_intersect_key($this->rule, array_flip($next)); } } - return $this->getInitialRules($use); + return $this->getInitialRules($next); } else { return array_intersect_key($this->rule, array_flip($sceneRule)); } @@ -333,7 +339,7 @@ class Validate extends RuleManager if (empty($this->events)) { return; } - + foreach ($this->events as $events) { list($callback, $param) = $events; if (class_exists($callback) && is_subclass_of($callback, ValidateEventAbstract::class)) { @@ -484,12 +490,14 @@ class Validate extends RuleManager */ private function init() { - $this->events = []; - $this->afters = []; - $this->befores = []; - $this->defaults = []; - $this->filters = []; - $this->eventPriority = true; + $this->events = []; + $this->afters = []; + $this->befores = []; + $this->defaults = []; + $this->filters = []; + $this->validatedData = []; + $this->validateFields = []; + $this->eventPriority = true; } /** diff --git a/tests/Material/ArticleValidate.php b/tests/Material/ArticleValidate.php index 3a33c3e..6aece9f 100644 --- a/tests/Material/ArticleValidate.php +++ b/tests/Material/ArticleValidate.php @@ -39,7 +39,7 @@ class ArticleValidate extends Validate protected $scene = [ 'add' => ['content', 'title'], - 'save' => ['use' => 'edit'], + 'save' => ['next' => 'edit'], 'del' => ['id'], ]; diff --git a/tests/Test/TestBug.php b/tests/Test/Fixer/TestScene.php similarity index 82% rename from tests/Test/TestBug.php rename to tests/Test/Fixer/TestScene.php index 127ceb1..f66a187 100644 --- a/tests/Test/TestBug.php +++ b/tests/Test/Fixer/TestScene.php @@ -10,16 +10,20 @@ * visited https://www.w7.cc for more details */ -namespace W7\Tests\Test; +namespace W7\Tests\Test\Fixer; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; -class TestBug extends BaseTestValidate +class TestScene extends BaseTestValidate { - public function testBug5() + /** + * @see https://gitee.com/we7coreteam/w7-engine-validate/pulls/5 + * @throws ValidateException + */ + public function testSceneCheckDataIsEmpty() { $v = new class extends Validate { public $checkData = []; @@ -43,7 +47,12 @@ class TestBug extends BaseTestValidate $this->assertEquals(123, $v->checkData['name']); } - public function testBug6() + /** + * @see https://gitee.com/we7coreteam/w7-engine-validate/pulls/3 + * @see https://gitee.com/we7coreteam/w7-engine-validate/pulls/6 + * @throws ValidateException + */ + public function testSceneAppendCheckField() { $v = new class extends Validate { protected $rule = [ diff --git a/tests/Test/TestValidateSceneUse.php b/tests/Test/TestValidateSceneUse.php new file mode 100644 index 0000000..2aee932 --- /dev/null +++ b/tests/Test/TestValidateSceneUse.php @@ -0,0 +1,74 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Exception\ValidateException; +use W7\Validate\Validate; + +class TestValidateSceneUse extends BaseTestValidate +{ + /** + * @test 测试use以及场景选择器的连续使用 + * @throws ValidateException + */ + public function testUse() + { + $testValidate = new class extends Validate { + protected $rule = [ + 'a' => 'required', + 'b' => 'required', + 'c' => 'required', + 'd' => 'required', + 'e' => 'required', + + 'f' => 'required', + 'g' => 'required', + + 'h' => 'required', + 'i' => 'required', + + 'not' => ' required' + ]; + + protected $scene = [ + 'testA' => ['a', 'b', 'c', 'next' => 'testB'], + 'testB' => ['c', 'd', 'next' => 'testC'], + 'testC' => ['e', 'next' => 'checkCode'], + 'testD' => ['f', 'g', 'next' => 'testE'], + 'testE' => ['h', 'i'], + ]; + + protected function checkCodeSelector(array $data) + { + return 'testD'; + } + }; + + $data = $testValidate::make()->scene('testA')->check([ + 'a' => 1, + 'b' => '666', + 'c' => '456', + 'd' => '585', + 'e' => 1, + + 'f' => 2, + 'g' => 2, + + 'h' => 12, + 'i' => 23 + ]); + + $this->assertCount(9, $data); + } +} -- Gitee From c8618b9e1e5e596cce34c128bdb93ed6ed3875b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 24 Jun 2021 11:43:14 +0800 Subject: [PATCH 106/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E6=B3=A8?= =?UTF-8?q?=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 48e7840..07604fb 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -109,8 +109,16 @@ class Validate extends RuleManager */ private $checkData = []; + /** + * Data validated this time + * @var array + */ private $validatedData = []; + /** + * Fields validated this time + * @var array + */ private $validateFields = []; /** @@ -205,7 +213,7 @@ class Validate extends RuleManager * * @param string|null $sceneName The scene name, or the current scene name if not provided. * @return array - * @throws ValidateException + * @throws ValidationException */ public function getInitialRules(?string $sceneName = ''): array { @@ -263,9 +271,14 @@ class Validate extends RuleManager // Pre-validation if (!empty($sceneRule)) { // Validated fields are not re-validated - $checkFields = array_diff($sceneRule, $this->validateFields); - $checkRules = $this->getCheckRules(array_intersect_key($this->rule, array_flip($checkFields))); - $data = $this->getValidationFactory()->make($this->checkData, $checkRules, $this->message, $this->customAttributes)->validate(); + $checkFields = array_diff($sceneRule, $this->validateFields); + $checkRules = $this->getCheckRules(array_intersect_key($this->rule, array_flip($checkFields))); + $data = $this->getValidationFactory()->make( + $this->checkData, + $checkRules, + $this->message, + $this->customAttributes + )->validate(); $this->validateFields = array_merge($this->validateFields, $checkFields); $this->validatedData = array_merge($this->validatedData, $data); } -- Gitee From aa83b6ec5224e31f25e85325ff6d5a80fcde7d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 24 Jun 2021 15:06:16 +0800 Subject: [PATCH 107/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DProvider?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Providers/Laravel/ValidateProvider.php | 3 ++- src/Providers/Rangine/ValidateProvider.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Providers/Laravel/ValidateProvider.php b/src/Providers/Laravel/ValidateProvider.php index 69647b7..662705f 100644 --- a/src/Providers/Laravel/ValidateProvider.php +++ b/src/Providers/Laravel/ValidateProvider.php @@ -12,12 +12,13 @@ namespace W7\Validate\Providers\Laravel; +use Illuminate\Support\Facades\App; use Illuminate\Support\ServiceProvider; use W7\Validate\Support\Storage\ValidateConfig; class ValidateProvider extends ServiceProvider { - public function register() + public function boot() { ValidateConfig::instance()->setFactory(App::make('validator')); } diff --git a/src/Providers/Rangine/ValidateProvider.php b/src/Providers/Rangine/ValidateProvider.php index 4a0e699..1a122df 100644 --- a/src/Providers/Rangine/ValidateProvider.php +++ b/src/Providers/Rangine/ValidateProvider.php @@ -23,7 +23,7 @@ class ValidateProvider extends ProviderAbstract * * @return void */ - public function register() + public function boot() { ValidateConfig::instance()->setFactory(Container::get("W7\Contract\Validation\ValidatorFactoryInterface")); } -- Gitee From 3045c5ab8cf93d826a735fa8bba3fad1b9909259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 24 Jun 2021 19:30:51 +0800 Subject: [PATCH 108/152] =?UTF-8?q?[U]=20=E5=9C=A8=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E4=B8=AD=E6=8C=87=E5=AE=9A=E7=9A=84=E4=BA=8B=E4=BB=B6=E4=BC=9A?= =?UTF-8?q?=E5=9C=A8=E5=BD=93=E5=89=8D=E5=9C=BA=E6=99=AF=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=90=8E=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 85 +++++---- ...SceneUse.php => TestValidateSceneNext.php} | 6 +- tests/Test/TestValidateSceneNextAndEvent.php | 180 ++++++++++++++++++ 3 files changed, 230 insertions(+), 41 deletions(-) rename tests/Test/{TestValidateSceneUse.php => TestValidateSceneNext.php} (91%) create mode 100644 tests/Test/TestValidateSceneNextAndEvent.php diff --git a/src/Validate.php b/src/Validate.php index 07604fb..f7c11b2 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -165,36 +165,8 @@ class Validate extends RuleManager $this->defaults = array_merge($this->default, $this->defaults); $this->filters = array_merge($this->filter, $this->filters); $data = $this->handleDefault($data, $fields); - - if ($this->filled) { - $rule = $this->addFilledRule($rule); - } - - if ($this->bail) { - $rule = $this->addBailRule($rule); - } - - if ($this->eventPriority) { - $this->handleEvent($data, 'beforeValidate'); - $this->handleCallback($data, 1); - } else { - $this->handleCallback($data, 1); - $this->handleEvent($data, 'beforeValidate'); - } - - $data = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes)->validate(); - $data = array_merge($this->validatedData, $data); - $data = $this->handlerFilter($data, $fields); - - if ($this->eventPriority) { - $this->handleCallback($data, 2); - $this->handleEvent($data, 'afterValidate'); - } else { - $this->handleEvent($data, 'afterValidate'); - $this->handleCallback($data, 2); - } - - return $data; + $data = $this->pass($data, $rule); + return $this->handlerFilter($data, $fields); } catch (ValidationException $e) { $errors = $this->getMessageProvider()->handleMessage($e->errors()); $errorMessage = ''; @@ -208,6 +180,48 @@ class Validate extends RuleManager } } + /** + * @param array $data + * @param array $rule + * @return array + * @throws ValidateException + * @throws ValidationException + */ + private function pass(array $data, array $rule): array + { + if ($this->filled) { + $rule = $this->addFilledRule($rule); + } + + if ($this->bail) { + $rule = $this->addBailRule($rule); + } + + if ($this->eventPriority) { + $this->handleEvent($data, 'beforeValidate'); + $this->handleCallback($data, 1); + } else { + $this->handleCallback($data, 1); + $this->handleEvent($data, 'beforeValidate'); + } + + $data = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes)->validate(); + $data = array_merge($this->validatedData, $data); + + if ($this->eventPriority) { + $this->handleCallback($data, 2); + $this->handleEvent($data, 'afterValidate'); + } else { + $this->handleEvent($data, 'afterValidate'); + $this->handleCallback($data, 2); + } + + $this->afters = []; + $this->befores = []; + $this->events = []; + return $data; + } + /** * Get initial rules provided * @@ -271,14 +285,9 @@ class Validate extends RuleManager // Pre-validation if (!empty($sceneRule)) { // Validated fields are not re-validated - $checkFields = array_diff($sceneRule, $this->validateFields); - $checkRules = $this->getCheckRules(array_intersect_key($this->rule, array_flip($checkFields))); - $data = $this->getValidationFactory()->make( - $this->checkData, - $checkRules, - $this->message, - $this->customAttributes - )->validate(); + $checkFields = array_diff($sceneRule, $this->validateFields); + $checkRules = $this->getCheckRules(array_intersect_key($this->rule, array_flip($checkFields))); + $data = $this->pass($this->checkData, $checkRules); $this->validateFields = array_merge($this->validateFields, $checkFields); $this->validatedData = array_merge($this->validatedData, $data); } diff --git a/tests/Test/TestValidateSceneUse.php b/tests/Test/TestValidateSceneNext.php similarity index 91% rename from tests/Test/TestValidateSceneUse.php rename to tests/Test/TestValidateSceneNext.php index 2aee932..a9fd170 100644 --- a/tests/Test/TestValidateSceneUse.php +++ b/tests/Test/TestValidateSceneNext.php @@ -16,13 +16,13 @@ use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; use W7\Validate\Validate; -class TestValidateSceneUse extends BaseTestValidate +class TestValidateSceneNext extends BaseTestValidate { /** - * @test 测试use以及场景选择器的连续使用 + * @test 测试Next以及场景选择器的连续使用 * @throws ValidateException */ - public function testUse() + public function testNext() { $testValidate = new class extends Validate { protected $rule = [ diff --git a/tests/Test/TestValidateSceneNextAndEvent.php b/tests/Test/TestValidateSceneNextAndEvent.php new file mode 100644 index 0000000..bb371ef --- /dev/null +++ b/tests/Test/TestValidateSceneNextAndEvent.php @@ -0,0 +1,180 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use PHPUnit\Framework\Assert; +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Support\Event\ValidateEventAbstract; +use W7\Validate\Validate; + +class Count +{ + public static $globalEventCount = 0; + public static $eventInSceneCount = 0; + public static $standaloneEventCount = 0; +} +class TestEvent extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + Count::$globalEventCount++; + return true; + } + + public function beforeValidate(): bool + { + Count::$globalEventCount++; + return true; + } +} + +class EventInScene extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + Count::$eventInSceneCount++; + return true; + } + + public function beforeValidate(): bool + { + Count::$eventInSceneCount++; + return true; + } +} + +class StandaloneEvent extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + Count::$standaloneEventCount++; + return true; + } + + public function beforeValidate(): bool + { + Count::$standaloneEventCount++; + return true; + } +} +class TestValidateSceneNextAndEvent extends BaseTestValidate +{ + public function testAssociatedSceneEvents() + { + $v = new class extends Validate { + public $afters = []; + + public $befores = []; + + protected $rule = [ + 'a' => 'required', + 'b' => 'required', + 'c' => 'required', + ]; + + protected $event = [ + TestEvent::class + ]; + + protected $scene = [ + 'testA' => ['before' => 'aEvent', 'a', 'next' => 'testB', 'after' => 'aEvent'], + 'testB' => ['before' => 'bEvent', 'b', 'next' => 'testC', 'after' => 'bEvent', 'event' => EventInScene::class], + 'testC' => ['c', 'event' => EventInScene::class], + + 'standalone' => ['a', 'before' => 'standalone', 'after' => 'standalone', 'event' => StandaloneEvent::class] + ]; + + protected $filter = [ + 'a' => 'intval' + ]; + + protected function afterStandalone(array $data) + { + Assert::assertEquals('string', gettype($data['a'])); + $this->afters['standalone'] = ($this->afters['standalone'] ?? 0) + 1; + return true; + } + + protected function beforeStandalone() + { + $this->befores['standalone'] = ($this->befores['standalone'] ?? 0) + 1; + return true; + } + + protected function afterAEvent($data) + { + Assert::assertEquals('string', gettype($data['a'])); + $this->afters['a'] = ($this->afters['a'] ?? 0) + 1; + return true; + } + + protected function beforeAEvent($data) + { + $this->befores['a'] = ($this->befores['a'] ?? 0) + 1; + return true; + } + + protected function afterBEvent($data) + { + $this->afters['b'] = ($this->afters['b'] ?? 0) + 1; + return true; + } + + protected function beforeBEvent($data) + { + Assert::assertEquals('string', gettype($data['a'])); + $this->befores['b'] = ($this->befores['b'] ?? 0) + 1; + return true; + } + }; + + $this->assertEquals(0, Count::$globalEventCount); + $this->assertEquals(0, Count::$eventInSceneCount); + $data = $v->scene('testA')->check([ + 'a' => '1', + 'b' => 2, + 'c' => 3 + ]); + $this->assertEquals(2, Count::$globalEventCount); + $this->assertEquals(4, Count::$eventInSceneCount); + + $this->assertArrayHasKey('a', $v->afters); + $this->assertArrayHasKey('a', $v->befores); + + $this->assertArrayHasKey('b', $v->afters); + $this->assertArrayHasKey('b', $v->befores); + + $this->assertEquals(1, $v->afters['a']); + $this->assertEquals(1, $v->afters['b']); + + $this->assertEquals(1, $v->befores['a']); + $this->assertEquals(1, $v->befores['b']); + + $this->assertEquals('integer', gettype($data['a'])); + $this->assertTrue(empty(array_diff_key($data, array_flip(['a', 'b', 'c'])))); + + $this->assertEquals(0, Count::$standaloneEventCount); + $data = $v->scene('standalone')->check([ + 'a' => '1' + ]); + $this->assertEquals(2, Count::$standaloneEventCount); + + $this->assertArrayHasKey('standalone', $v->afters); + $this->assertArrayHasKey('standalone', $v->befores); + + $this->assertEquals(1, $v->afters['standalone']); + $this->assertEquals(1, $v->befores['standalone']); + + $this->assertEquals(1, $data['a']); + } +} -- Gitee From afe8337052a37fba10b15a172ffaaaa81657b42d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 24 Jun 2021 19:34:39 +0800 Subject: [PATCH 109/152] =?UTF-8?q?[A]=20=E9=AA=8C=E8=AF=81=E9=9B=86?= =?UTF-8?q?=E5=90=88=E5=A2=9E=E5=8A=A0=E6=95=B0=E7=BB=84=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Storage/ValidateCollection.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 2851f9a..7d6576c 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -146,4 +146,9 @@ class ValidateCollection extends Collection { $this->offsetSet($key, $value); } + + public function __toArray(): array + { + return $this->toArray(); + } } -- Gitee From d74deac33ce915467922779a9af7107eef451a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 25 Jun 2021 14:06:20 +0800 Subject: [PATCH 110/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E5=9C=A8?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E5=99=A8=E4=B8=8A=E4=BD=BF=E7=94=A8=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E6=9D=A5=E8=8E=B7=E5=8F=96=E8=A7=84=E5=88=99=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index f7c11b2..ad87f34 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -160,7 +160,7 @@ class Validate extends RuleManager $this->init(); $this->checkData = $data; $this->addEvent($this->event); - $rule = $this->getCheckRules($this->getInitialRules()); + $rule = $this->getCheckRules($this->getSceneRules()); $fields = array_merge(array_keys($rule), $this->validateFields); $this->defaults = array_merge($this->default, $this->defaults); $this->filters = array_merge($this->filter, $this->filters); @@ -223,13 +223,13 @@ class Validate extends RuleManager } /** - * Get initial rules provided + * Get the rules that need to be validation in the scene * * @param string|null $sceneName The scene name, or the current scene name if not provided. * @return array - * @throws ValidationException + * @throws ValidationException|ValidateException */ - public function getInitialRules(?string $sceneName = ''): array + private function getSceneRules(?string $sceneName = ''): array { if ('' === $sceneName) { $sceneName = $this->getCurrentSceneName(); @@ -299,7 +299,7 @@ class Validate extends RuleManager return array_intersect_key($this->rule, array_flip($next)); } } - return $this->getInitialRules($next); + return $this->getSceneRules($next); } else { return array_intersect_key($this->rule, array_flip($sceneRule)); } -- Gitee From 273240a4ee2a9b55bb188c912784acd60accd79e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 25 Jun 2021 17:12:22 +0800 Subject: [PATCH 111/152] =?UTF-8?q?[A]=20=E6=94=AF=E6=8C=81=E5=9C=A8?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E5=9C=BA=E6=99=AF=E4=B8=AD=E6=8C=87?= =?UTF-8?q?=E5=AE=9A=E4=B8=8B=E4=B8=80=E4=B8=AA=E5=9C=BA=E6=99=AF=20[U]=20?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=85=A8=E5=B1=80=E4=BA=8B=E4=BB=B6=E6=B0=B8?= =?UTF-8?q?=E8=BF=9C=E5=9C=A8=E6=9C=80=E5=A4=96=E5=B1=82=20[U]=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=9C=BA=E6=99=AF=E4=B8=AD=E6=8C=87=E5=AE=9A=E4=BA=86?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC=E5=92=8C=E8=BF=87=E6=BB=A4=E5=99=A8?= =?UTF-8?q?=E5=88=99=E5=9C=A8=E5=BD=93=E5=89=8D=E9=AA=8C=E8=AF=81=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E5=A3=B0=E6=98=8E=E5=91=A8=E6=9C=9F=E5=86=85=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=AE=8C=E6=AF=95=20[D]=20=E5=88=A0=E9=99=A4=E4=B8=AD?= =?UTF-8?q?=E9=97=B4=E4=BB=B6=E9=83=A8=E5=88=86=EF=BC=8C=E5=A6=82=E6=9E=9C?= =?UTF-8?q?=E9=9C=80=E8=A6=81=EF=BC=8C=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94=A8?= =?UTF-8?q?itwmw/engine-validate-middleware?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 2 +- .../Concerns/ValidateFactoryInterface.php | 27 --- .../Middleware/Laravel/ValidateMiddleware.php | 34 ---- .../Middleware/Rangine/ValidateMiddleware.php | 42 ----- src/Support/RuleManagerScene.php | 2 +- src/Support/Storage/ValidateFactory.php | 84 --------- .../Storage/ValidateMiddlewareConfig.php | 166 ------------------ src/Support/ValidateScene.php | 37 +++- src/Support/helpers.php | 23 --- src/Validate.php | 133 +++++++++----- tests/Material/Count.php | 48 +++++ tests/Test/TestHandlerEvent.php | 164 ++++++++++++++++- tests/Test/TestValidateSceneNextAndEvent.php | 94 ++++++++-- 13 files changed, 402 insertions(+), 454 deletions(-) delete mode 100644 src/Support/Concerns/ValidateFactoryInterface.php delete mode 100644 src/Support/Middleware/Laravel/ValidateMiddleware.php delete mode 100644 src/Support/Middleware/Rangine/ValidateMiddleware.php delete mode 100644 src/Support/Storage/ValidateFactory.php delete mode 100644 src/Support/Storage/ValidateMiddlewareConfig.php create mode 100644 tests/Material/Count.php diff --git a/src/RuleManager.php b/src/RuleManager.php index bc97743..b851c78 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -71,7 +71,7 @@ class RuleManager * @param string|null $name * @return $this */ - public function scene(?string $name): RuleManager + final public function scene(?string $name): RuleManager { $this->currentScene = $name; return $this; diff --git a/src/Support/Concerns/ValidateFactoryInterface.php b/src/Support/Concerns/ValidateFactoryInterface.php deleted file mode 100644 index a34e031..0000000 --- a/src/Support/Concerns/ValidateFactoryInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Validate\Support\Concerns; - -use W7\Validate\Validate; - -interface ValidateFactoryInterface -{ - /** - * Get validator based on controller - * - * @param string $controller - * @param string $scene - * @return false|Validate - */ - public function getValidate(string $controller, string $scene = ''); -} diff --git a/src/Support/Middleware/Laravel/ValidateMiddleware.php b/src/Support/Middleware/Laravel/ValidateMiddleware.php deleted file mode 100644 index 28b3562..0000000 --- a/src/Support/Middleware/Laravel/ValidateMiddleware.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Validate\Support\Middleware\Laravel; - -use Closure; -use Illuminate\Http\Request; -use W7\Validate\Support\Storage\ValidateMiddlewareConfig; - -class ValidateMiddleware -{ - public function handle(Request $request, Closure $next) - { - list($controller, $scene) = explode('@', $request->route()->getActionName()); - - $validator = ValidateMiddlewareConfig::instance()->getValidateFactory()->getValidate($controller, $scene); - - if ($validator) { - $data = $validator->check($request->all()); - $request->offsetSet('__validate__data__', $data); - } - - return $next($request); - } -} diff --git a/src/Support/Middleware/Rangine/ValidateMiddleware.php b/src/Support/Middleware/Rangine/ValidateMiddleware.php deleted file mode 100644 index 8ce6f7b..0000000 --- a/src/Support/Middleware/Rangine/ValidateMiddleware.php +++ /dev/null @@ -1,42 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Validate\Support\Middleware\Rangine; - -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Psr\Http\Server\RequestHandlerInterface; -use W7\Facade\Context; -use W7\Core\Middleware\MiddlewareAbstract; -use W7\Http\Message\Server\Request; -use W7\Validate\Support\Storage\ValidateMiddlewareConfig; - -class ValidateMiddleware extends MiddlewareAbstract -{ - public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface - { - $controller = $request->route->getController(); - $scene = $request->route->getAction(); - - $validator = ValidateMiddlewareConfig::instance()->getValidateFactory()->getValidate($controller, $scene); - - if ($validator) { - $data = array_merge([], $request->getQueryParams(), $request->getParsedBody(), $request->getUploadedFiles()); - $data = $validator->check($data); - /** @var Request $request */ - $request = $request->withAttribute('__validate__data__', $data); - Context::setRequest($request); - } - - return $handler->handle($request); - } -} diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php index a15a6f0..3fd2a47 100644 --- a/src/Support/RuleManagerScene.php +++ b/src/Support/RuleManagerScene.php @@ -20,7 +20,7 @@ class RuleManagerScene implements SceneInterface * The rules to be applied to the data. * @var array */ - protected $checkRules; + protected $checkRules = []; /** * All original validation rules diff --git a/src/Support/Storage/ValidateFactory.php b/src/Support/Storage/ValidateFactory.php deleted file mode 100644 index ec008f3..0000000 --- a/src/Support/Storage/ValidateFactory.php +++ /dev/null @@ -1,84 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Validate\Support\Storage; - -use Exception; -use W7\Validate\Support\Concerns\ValidateFactoryInterface; -use W7\Validate\Validate; - -class ValidateFactory implements ValidateFactoryInterface -{ - public function getValidate(string $controller, string $scene = '') - { - $haveLink = false; - $validate = ''; - - $validateLink = ValidateMiddlewareConfig::instance()->getValidateLink($controller); - if (!empty($validateLink)) { - # Specified validator for the specified controller method - if (isset($validateLink[$scene]) || isset($validateLink['!__other__'])) { - if (isset($validateLink['!__other__'])) { - $method = '!__other__'; - } else { - $method = $scene; - } - - # Specifies the validation scenario for the specified validator - if (is_array($validateLink[$method])) { - if (count($validateLink[$method]) >= 2) { - $validate = $validateLink[$method][0]; - $scene = $validateLink[$method][1]; - $haveLink = true; - } - } else { - $validate = $validateLink[$method]; - $haveLink = true; - } - } - } - - if (false === $haveLink) { - # Handles controllers with specified paths - $controllerPath = ''; - $validatePath = ''; - foreach (ValidateMiddlewareConfig::instance()->getAutoValidatePath() as $_controllerPath => $_validatePath) { - if (false !== strpos($controller, $_controllerPath)) { - $controllerPath = $_controllerPath; - $validatePath = $_validatePath; - break; - } - } - if (empty($controllerPath)) { - return false; - } - - $validate = str_replace($controllerPath, '', $controller); - $_namespace = explode('\\', $validate); - $fileName = str_replace('Controller', 'Validate', array_pop($_namespace)); - $_namespace = implode('\\', $_namespace); - $validate = $validatePath . $_namespace . (!empty($_namespace) ? '\\' : '') . $fileName; - } - - if (class_exists($validate)) { - if (is_subclass_of($validate, Validate::class)) { - /** @var Validate $validator */ - $validator = new $validate(); - $validator->scene($scene); - return $validator; - } - - throw new Exception("The given 'Validate' " . $validate . ' has to be a subtype of W7\Validate\Validate'); - } - return false; - } -} diff --git a/src/Support/Storage/ValidateMiddlewareConfig.php b/src/Support/Storage/ValidateMiddlewareConfig.php deleted file mode 100644 index 4bfbf8f..0000000 --- a/src/Support/Storage/ValidateMiddlewareConfig.php +++ /dev/null @@ -1,166 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Validate\Support\Storage; - -use W7\Validate\Support\Concerns\ValidateFactoryInterface; - -class ValidateMiddlewareConfig -{ - /** - * Automatic loading of validator rules - * @var array - */ - protected $autoValidatePath = []; - - /** - * Validator specific association - * @var array - */ - protected $validateLink = []; - - /** - * Validate Factory - * @var ValidateFactoryInterface - */ - protected $validateFactory; - - /** - * Stored single instance objects - * @var ValidateMiddlewareConfig - */ - protected static $instance; - - public static function instance(): ValidateMiddlewareConfig - { - if (empty(self::$instance)) { - self::$instance = new static(); - } - - return self::$instance; - } - - public function __construct() - { - $this->validateFactory = new ValidateFactory(); - } - - /** - * Set up auto-load validator rules - * - * @param string $controllerPath Controller path - * @param string $validatePath Validator path - * @return $this - */ - public function setAutoValidatePath(string $controllerPath, string $validatePath): ValidateMiddlewareConfig - { - if ('\\' !== substr($controllerPath, -1)) { - $controllerPath = $controllerPath . '\\'; - } - - if ('\\' !== substr($validatePath, -1)) { - $validatePath = $validatePath . '\\'; - } - - $this->autoValidatePath[$controllerPath] = $validatePath; - return $this; - } - - /** - * Set Validator Association - * - * @param string|string[] $controller Controller namespace - * To specify a method, pass an array with the second element being the method name - * @param string|string[] $validate Validator namespace - * To specify a scene, pass an array with the second element being the scene name - * @return $this - */ - public function setValidateLink($controller, $validate): ValidateMiddlewareConfig - { - if (is_array($controller)) { - $controllers = $controller; - $controller = $controllers[0]; - $method = $controllers[1]; - # The "\" symbol must not be present in the array - $controller = md5($controller); - if (count($controllers) >= 2) { - if (isset($this->validateLink[$controller])) { - $_validate = $this->validateLink[$controller]; - $_validate = array_merge($_validate, [ - $method => $validate - ]); - $this->validateLink[$controller] = $_validate; - } else { - $this->validateLink[$controller] = [ - $method => $validate - ]; - } - } - } else { - $controller = md5($controller); - if (isset($this->validateLink[$controller])) { - $this->validateLink[$controller]['!__other__'] = $validate; - } else { - $this->validateLink[$controller] = [ - '!__other__' => $validate - ]; - } - } - return $this; - } - - /** - * Get validator specific associations - * - * @param string|null $controller Validator full namespace - * @return array - */ - public function getValidateLink(?string $controller = null): array - { - if (null === $controller) { - return $this->validateLink; - } - return $this->validateLink[md5($controller)] ?? []; - } - - /** - * Get auto-load validator rules - * - * @return array - */ - public function getAutoValidatePath(): array - { - return $this->autoValidatePath; - } - - /** - * Provide a validate factory - * - * @param ValidateFactoryInterface $validateFactory - * @return $this - */ - public function setValidateFactory(ValidateFactoryInterface $validateFactory): ValidateMiddlewareConfig - { - $this->validateFactory = $validateFactory; - return $this; - } - - /** - * Get a validate factory - * - * @return ValidateFactoryInterface - */ - public function getValidateFactory(): ValidateFactoryInterface - { - return $this->validateFactory; - } -} diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 6054357..6a10d61 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -14,7 +14,7 @@ namespace W7\Validate\Support; use Closure; use Illuminate\Support\Arr; -use RuntimeException; +use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\Concerns\DefaultInterface; use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Rule\BaseRule; @@ -24,12 +24,13 @@ use W7\Validate\Support\Storage\ValidateCollection; * Class ValidateScene * @package W7\Validate\Support * - * @property-read array $events Events to be processed for this validate - * @property-read array $befores Methods to be executed before this validate - * @property-read array $afters Methods to be executed after this validate - * @property-read array $defaults This validation requires a default value for the value - * @property-read array $filters The filter. This can be a global function name, anonymous function, etc. - * @property-read bool $eventPriority Event Priority + * @property-read array $events Events to be processed for this validate + * @property-read array $befores Methods to be executed before this validate + * @property-read array $afters Methods to be executed after this validate + * @property-read array $defaults This validation requires a default value for the value + * @property-read array $filters The filter. This can be a global function name, anonymous function, etc. + * @property-read bool $eventPriority Event Priority + * @property-read string $next Next scene or next scene selector */ class ValidateScene extends RuleManagerScene { @@ -73,7 +74,13 @@ class ValidateScene extends RuleManagerScene * Event Priority * @var bool */ - private $eventPriority; + private $eventPriority = true; + + /** + * Next scene or next scene selector + * @var string + */ + private $next; /** * ValidateScene constructor. @@ -226,6 +233,18 @@ class ValidateScene extends RuleManagerScene return $this; } + /** + * Specify the next scene or next scene selector + * + * @param string $name + * @return $this + */ + public function next(string $name): ValidateScene + { + $this->next = $name; + return $this; + } + /** * Provide the data to be validated * @@ -269,6 +288,6 @@ class ValidateScene extends RuleManagerScene return $this->$name; } - throw new RuntimeException('Unknown property:' . $name); + throw new ValidateRuntimeException('Unknown property:' . $name); } } diff --git a/src/Support/helpers.php b/src/Support/helpers.php index 64fad0a..202222e 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -10,8 +10,6 @@ * visited https://www.w7.cc for more details */ -use Psr\Http\Message\ServerRequestInterface; -use Illuminate\Http\Request; use W7\Validate\Support\Storage\ValidateCollection; if (!function_exists('validate_collect')) { @@ -25,24 +23,3 @@ if (!function_exists('validate_collect')) { return new ValidateCollection($value); } } - -if (!function_exists('get_validate_data')) { - /** - * Get the result after verification - * - * @param ServerRequestInterface|Request $request Request Example - * @return ValidateCollection - */ - function get_validate_data($request = null): ValidateCollection - { - if ($request instanceof ServerRequestInterface) { - $data = $request->getAttribute('__validate__data__'); - } elseif ($request instanceof Request) { - $data = $request->offsetGet('__validate__data__'); - } else { - $data = []; - } - - return validate_collect($data); - } -} diff --git a/src/Validate.php b/src/Validate.php index ad87f34..85a37d0 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -160,13 +160,14 @@ class Validate extends RuleManager $this->init(); $this->checkData = $data; $this->addEvent($this->event); - $rule = $this->getCheckRules($this->getSceneRules()); - $fields = array_merge(array_keys($rule), $this->validateFields); - $this->defaults = array_merge($this->default, $this->defaults); - $this->filters = array_merge($this->filter, $this->filters); - $data = $this->handleDefault($data, $fields); - $data = $this->pass($data, $rule); - return $this->handlerFilter($data, $fields); + $this->handleEvent($data, 'beforeValidate'); + $events = $this->events; + $this->events = []; + $rule = $this->getCheckRules($this->getSceneRules()); + $data = $this->pass($data, $rule); + $this->events = $events; + $this->handleEvent($data, 'afterValidate'); + return $data; } catch (ValidationException $e) { $errors = $this->getMessageProvider()->handleMessage($e->errors()); $errorMessage = ''; @@ -181,14 +182,19 @@ class Validate extends RuleManager } /** - * @param array $data - * @param array $rule + * Perform data validation and processing + * + * @param array $data Data to be verified + * @param array $rule Rules for validation * @return array * @throws ValidateException * @throws ValidationException */ private function pass(array $data, array $rule): array { + $this->defaults = array_merge($this->default, $this->defaults); + $this->filters = array_merge($this->filter, $this->filters); + if ($this->filled) { $rule = $this->addFilledRule($rule); } @@ -197,6 +203,10 @@ class Validate extends RuleManager $rule = $this->addBailRule($rule); } + // Defaults and filters only handle the fields that are being validated now + $fields = array_keys($rule); + $data = $this->handleDefault($data, $fields); + if ($this->eventPriority) { $this->handleEvent($data, 'beforeValidate'); $this->handleCallback($data, 1); @@ -205,7 +215,9 @@ class Validate extends RuleManager $this->handleEvent($data, 'beforeValidate'); } - $data = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes)->validate(); + if (!empty($rule)) { + $data = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes)->validate(); + } $data = array_merge($this->validatedData, $data); if ($this->eventPriority) { @@ -216,9 +228,8 @@ class Validate extends RuleManager $this->handleCallback($data, 2); } - $this->afters = []; - $this->befores = []; - $this->events = []; + $data = $this->handlerFilter($data, $fields); + $this->initScene(); return $data; } @@ -242,13 +253,18 @@ class Validate extends RuleManager if (method_exists($this, 'scene' . ucfirst($sceneName))) { $scene = new ValidateScene($this->rule, $this->checkData); call_user_func([$this, 'scene' . ucfirst($sceneName)], $scene); - $this->event = array_merge($this->event, $scene->events); - $this->afters = array_merge($this->afters, $scene->afters); - $this->befores = array_merge($this->befores, $scene->befores); - $this->defaults = array_merge($this->defaults, $scene->defaults); - $this->filters = array_merge($this->filters, $scene->filters); + $this->events = $scene->events; + $this->afters = $scene->afters; + $this->befores = $scene->befores; + $this->defaults = $scene->defaults; + $this->filters = $scene->filters; $this->eventPriority = $scene->eventPriority; - return $scene->getRules(); + $next = $scene->next; + $sceneRule = $scene->getRules(); + if (!empty($next)) { + return $this->next($scene->next, $sceneRule, $sceneName); + } + return $sceneRule; } if (isset($this->scene[$sceneName])) { @@ -274,32 +290,11 @@ class Validate extends RuleManager $this->addAfter($callback); unset($sceneRule['after']); } - if (isset($sceneRule['next']) && !empty($sceneRule['next'])) { $next = $sceneRule['next']; - if ($next === $sceneName) { - throw new LogicException('The scene used cannot be the same as the current scene.'); - } unset($sceneRule['next']); - - // Pre-validation - if (!empty($sceneRule)) { - // Validated fields are not re-validated - $checkFields = array_diff($sceneRule, $this->validateFields); - $checkRules = $this->getCheckRules(array_intersect_key($this->rule, array_flip($checkFields))); - $data = $this->pass($this->checkData, $checkRules); - $this->validateFields = array_merge($this->validateFields, $checkFields); - $this->validatedData = array_merge($this->validatedData, $data); - } - - // If a scene selector exists - if (method_exists($this, lcfirst($next) . 'Selector')) { - $next = call_user_func([$this, lcfirst($next) . 'Selector'], $this->validatedData); - if (is_array($next)) { - return array_intersect_key($this->rule, array_flip($next)); - } - } - return $this->getSceneRules($next); + $rules = $this->getCheckRules(array_intersect_key($this->rule, array_flip($sceneRule))); + return $this->next($next, $rules, $sceneName); } else { return array_intersect_key($this->rule, array_flip($sceneRule)); } @@ -308,6 +303,40 @@ class Validate extends RuleManager return $this->rule; } + /** + * Processing the next scene + * + * @param string $next Next scene name or scene selector + * @param array $rules Validation rules + * @param string $currentSceneName Current scene name + * @return array + * @throws ValidateException + * @throws ValidationException + */ + private function next(string $next, array $rules, string $currentSceneName = ''): array + { + if ($next === $currentSceneName) { + throw new LogicException('The scene used cannot be the same as the current scene.'); + } + + // Pre-validation + // Validated fields are not re-validated + $checkFields = array_diff(array_keys($rules), $this->validateFields); + $checkRules = array_intersect_key($rules, array_flip($checkFields)); + $data = $this->pass($this->checkData, $checkRules); + $this->validateFields = array_merge($this->validateFields, $checkFields); + $this->validatedData = array_merge($this->validatedData, $data); + + // If a scene selector exists + if (method_exists($this, lcfirst($next) . 'Selector')) { + $next = call_user_func([$this, lcfirst($next) . 'Selector'], $this->validatedData); + if (is_array($next)) { + return array_intersect_key($this->rule, array_flip($next)); + } + } + return $this->getSceneRules($next); + } + /** * Processing method * @@ -512,14 +541,22 @@ class Validate extends RuleManager */ private function init() { - $this->events = []; - $this->afters = []; - $this->befores = []; - $this->defaults = []; - $this->filters = []; $this->validatedData = []; $this->validateFields = []; - $this->eventPriority = true; + $this->initScene(); + } + + /** + * Initialization validation scene + */ + private function initScene() + { + $this->afters = []; + $this->befores = []; + $this->events = []; + $this->defaults = []; + $this->filters = []; + $this->eventPriority = true; } /** diff --git a/tests/Material/Count.php b/tests/Material/Count.php new file mode 100644 index 0000000..7596798 --- /dev/null +++ b/tests/Material/Count.php @@ -0,0 +1,48 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Material; + +class Count +{ + private static $count; + + public static function incremental(string $name) + { + self::$count[$name] = (self::$count[$name] ?? 0) + 1; + } + + public static function decrease(string $name) + { + self::$count[$name] = (self::$count[$name] ?? 0) - 1; + } + + public static function reset(string $name) + { + self::$count[$name] = 0; + } + + public static function value(string $name, int $value = null) + { + if (null === $value) { + return self::$count[$name] ?? 0; + } + + self::$count[$name] = $value; + return $value; + } + + public static function __callStatic($name, $arguments) + { + return self::value($name, ...$arguments); + } +} diff --git a/tests/Test/TestHandlerEvent.php b/tests/Test/TestHandlerEvent.php index 8939077..58cf3db 100644 --- a/tests/Test/TestHandlerEvent.php +++ b/tests/Test/TestHandlerEvent.php @@ -12,11 +12,101 @@ namespace W7\Tests\Test; +use PHPUnit\Framework\Assert; use W7\Tests\Material\BaseTestValidate; -use W7\Tests\Material\HandlerEventValidate; +use W7\Tests\Material\Count; use W7\Tests\Material\TestValidate; use W7\Validate\Exception\ValidateException; +use W7\Validate\Support\Event\ValidateEventAbstract; +use W7\Validate\Support\ValidateScene; +use W7\Validate\Validate; +class TestGlobalEvent extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + Assert::assertEquals(1, Count::value('sceneEventAfter-A')); + Assert::assertEquals(1, Count::value('sceneEventAfter-B')); + Assert::assertEquals(1, Count::value('sceneEventAfter-C')); + Assert::assertEquals(1, Count::value('testAfter')); + Assert::assertEquals(1, Count::value('customSceneEventAfter')); + + Count::incremental('globalEventAfter'); + return true; + } + + public function beforeValidate(): bool + { + Assert::assertEquals(0, Count::value('sceneEventBefore-A')); + Assert::assertEquals(0, Count::value('sceneEventBefore-B')); + Assert::assertEquals(0, Count::value('sceneEventBefore-C')); + Assert::assertEquals(0, Count::value('testBefore')); + Assert::assertEquals(0, Count::value('customSceneEventBefore')); + + Count::incremental('globalEventBefore'); + return true; + } +} + +class TestSceneEventA extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + Count::incremental('sceneEventAfter-A'); + return true; + } + + public function beforeValidate(): bool + { + Count::incremental('sceneEventBefore-A'); + return true; + } +} + +class TestSceneEventB extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + Count::incremental('sceneEventAfter-B'); + return true; + } + + public function beforeValidate(): bool + { + Count::incremental('sceneEventBefore-B'); + return true; + } +} + +class TestSceneEventC extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + Count::incremental('sceneEventAfter-C'); + return true; + } + + public function beforeValidate(): bool + { + Count::incremental('sceneEventBefore-C'); + return true; + } +} + +class TestCustomSceneEvent extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + Count::incremental('customSceneEventAfter'); + return true; + } + + public function beforeValidate(): bool + { + Count::incremental('customSceneEventBefore'); + return true; + } +} class TestHandlerEvent extends BaseTestValidate { public function testErrorEvent() @@ -46,4 +136,76 @@ class TestHandlerEvent extends BaseTestValidate $this->expectExceptionMessage('error'); $v->scene('beforeThrowError')->check([]); } + + /** + * @test 测试事件在场景中是否正确运行,以及全局事件和场景事件的执行顺序是否正确 + * + * 全局事件before->场景事件->全局事件after + * @throws ValidateException + */ + public function testEventExecution() + { + $v = new class extends Validate { + protected $event = [ + TestGlobalEvent::class + ]; + + protected $scene = [ + 'testA' => ['event' => TestSceneEventA::class, 'next' => 'testB'], + 'testB' => ['event' => [TestSceneEventB::class, TestSceneEventC::class], 'next' => 'testC'], + 'testC' => ['before' => 'testBefore', 'after' => 'testAfter', 'next' => 'testD'] + ]; + + protected function sceneTestD(ValidateScene $scene) + { + $scene->after('customSceneEvent') + ->before('customSceneEvent') + ->event(TestCustomSceneEvent::class); + } + + protected function beforeCustomSceneEvent() + { + Count::incremental('beforeCustomSceneEvent'); + return true; + } + + protected function afterCustomSceneEvent() + { + Count::incremental('afterCustomSceneEvent'); + return true; + } + + protected function beforeTestBefore() + { + Count::incremental('testBefore'); + return true; + } + + protected function afterTestAfter() + { + Count::incremental('testAfter'); + return true; + } + }; + + $v->scene('testA')->check([]); + + $this->assertEquals(1, Count::value('testBefore')); + $this->assertEquals(1, Count::value('testAfter')); + + $this->assertEquals(1, Count::value('sceneEventAfter-A')); + $this->assertEquals(1, Count::value('sceneEventBefore-A')); + + $this->assertEquals(1, Count::value('sceneEventAfter-B')); + $this->assertEquals(1, Count::value('sceneEventBefore-B')); + + $this->assertEquals(1, Count::value('sceneEventAfter-C')); + $this->assertEquals(1, Count::value('sceneEventBefore-C')); + + $this->assertEquals(1, Count::value('globalEventAfter')); + $this->assertEquals(1, Count::value('globalEventBefore')); + + $this->assertEquals(1, Count::value('customSceneEventAfter')); + $this->assertEquals(1, Count::value('customSceneEventBefore')); + } } diff --git a/tests/Test/TestValidateSceneNextAndEvent.php b/tests/Test/TestValidateSceneNextAndEvent.php index bb371ef..eb65470 100644 --- a/tests/Test/TestValidateSceneNextAndEvent.php +++ b/tests/Test/TestValidateSceneNextAndEvent.php @@ -14,26 +14,23 @@ namespace W7\Tests\Test; use PHPUnit\Framework\Assert; use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\Count; +use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Event\ValidateEventAbstract; +use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; -class Count -{ - public static $globalEventCount = 0; - public static $eventInSceneCount = 0; - public static $standaloneEventCount = 0; -} class TestEvent extends ValidateEventAbstract { public function afterValidate(): bool { - Count::$globalEventCount++; + Count::incremental('globalEventCount'); return true; } public function beforeValidate(): bool { - Count::$globalEventCount++; + Count::incremental('globalEventCount'); return true; } } @@ -42,13 +39,13 @@ class EventInScene extends ValidateEventAbstract { public function afterValidate(): bool { - Count::$eventInSceneCount++; + Count::incremental('eventInSceneCount'); return true; } public function beforeValidate(): bool { - Count::$eventInSceneCount++; + Count::incremental('eventInSceneCount'); return true; } } @@ -57,13 +54,13 @@ class StandaloneEvent extends ValidateEventAbstract { public function afterValidate(): bool { - Count::$standaloneEventCount++; + Count::incremental('standaloneEventCount'); return true; } public function beforeValidate(): bool { - Count::$standaloneEventCount++; + Count::incremental('standaloneEventCount'); return true; } } @@ -138,15 +135,15 @@ class TestValidateSceneNextAndEvent extends BaseTestValidate } }; - $this->assertEquals(0, Count::$globalEventCount); - $this->assertEquals(0, Count::$eventInSceneCount); + $this->assertEquals(0, Count::globalEventCount()); + $this->assertEquals(0, Count::eventInSceneCount()); $data = $v->scene('testA')->check([ 'a' => '1', 'b' => 2, 'c' => 3 ]); - $this->assertEquals(2, Count::$globalEventCount); - $this->assertEquals(4, Count::$eventInSceneCount); + $this->assertEquals(2, Count::globalEventCount()); + $this->assertEquals(4, Count::eventInSceneCount()); $this->assertArrayHasKey('a', $v->afters); $this->assertArrayHasKey('a', $v->befores); @@ -163,11 +160,11 @@ class TestValidateSceneNextAndEvent extends BaseTestValidate $this->assertEquals('integer', gettype($data['a'])); $this->assertTrue(empty(array_diff_key($data, array_flip(['a', 'b', 'c'])))); - $this->assertEquals(0, Count::$standaloneEventCount); + $this->assertEquals(0, Count::standaloneEventCount()); $data = $v->scene('standalone')->check([ 'a' => '1' ]); - $this->assertEquals(2, Count::$standaloneEventCount); + $this->assertEquals(2, Count::standaloneEventCount()); $this->assertArrayHasKey('standalone', $v->afters); $this->assertArrayHasKey('standalone', $v->befores); @@ -177,4 +174,65 @@ class TestValidateSceneNextAndEvent extends BaseTestValidate $this->assertEquals(1, $data['a']); } + + /** + * @test 测试自定义场景中指定Next,检查默认值,过滤器以及场景验证等功能是否正常 + */ + public function testSceneNextForCustomScenes() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'required', + 'b' => '', + 'c' => 'required' + ]; + + protected $default = [ + 'a' => 1 + ]; + + protected $filter = [ + 'c' => 'intval' + ]; + + protected $scene = [ + 'testA' => ['a', 'next' => 'testB'], + 'testC' => ['c'] + ]; + + protected function sceneTestB(ValidateScene $scene) + { + $scene->only(['b']) + ->append('b', 'required') + ->filter('b', 'intval') + ->next('testC'); + } + }; + + try { + $v->scene('testA')->check([ + + ]); + } catch (ValidateException $e) { + $this->assertArrayHasKey('b', $e->getData()); + } + + try { + $v->scene('testA')->check([ + 'b' => '123' + ]); + } catch (ValidateException $e) { + $this->assertArrayHasKey('c', $e->getData()); + } + + $data = $v->scene('testA')->check([ + 'b' => '123', + 'c' => '256' + ]); + + $this->assertCount(3, $data); + foreach ($data as $value) { + $this->assertEquals('integer', gettype($value)); + } + } } -- Gitee From db5ba9de603ac9e167fd46d2b90826595060813b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 30 Jun 2021 15:56:22 +0800 Subject: [PATCH 112/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E5=9C=BA?= =?UTF-8?q?=E6=99=AFnext=E4=B8=AD=E8=BF=94=E5=9B=9E=E7=A9=BA=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E9=80=A0=E6=88=90=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E5=A6=82=E6=9E=9Cnext=E8=BF=94=E5=9B=9E=E7=A9=BA=E5=AD=97?= =?UTF-8?q?=E7=AC=A6=E6=88=96=E8=80=85false=E5=88=99=E5=BF=BD=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Validate.php b/src/Validate.php index 85a37d0..42c7e82 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -290,6 +290,7 @@ class Validate extends RuleManager $this->addAfter($callback); unset($sceneRule['after']); } + if (isset($sceneRule['next']) && !empty($sceneRule['next'])) { $next = $sceneRule['next']; unset($sceneRule['next']); @@ -334,6 +335,11 @@ class Validate extends RuleManager return array_intersect_key($this->rule, array_flip($next)); } } + + if (empty($next) || false === $next) { + return []; + } + return $this->getSceneRules($next); } -- Gitee From f0cefc381e3dd90a8faf69514eb6a2d6016ede77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 1 Jul 2021 11:42:33 +0800 Subject: [PATCH 113/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E5=9C=BA?= =?UTF-8?q?=E6=99=AFnext=E6=B2=A1=E6=9C=89=E8=A7=A3=E6=9E=90=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E8=A7=84=E5=88=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Validate.php b/src/Validate.php index 42c7e82..795745e 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -324,6 +324,7 @@ class Validate extends RuleManager // Validated fields are not re-validated $checkFields = array_diff(array_keys($rules), $this->validateFields); $checkRules = array_intersect_key($rules, array_flip($checkFields)); + $checkRules = $this->getCheckRules($checkRules); $data = $this->pass($this->checkData, $checkRules); $this->validateFields = array_merge($this->validateFields, $checkFields); $this->validatedData = array_merge($this->validatedData, $data); -- Gitee From 78800e616f4f3f9528ca111433277171f140a124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 1 Jul 2021 19:06:18 +0800 Subject: [PATCH 114/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E9=93=BE=E4=B8=AD=E9=87=8D=E5=A4=8D=E7=9A=84=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E5=AD=97=E6=AE=B5=E4=BC=9A=E9=AA=8C=E8=AF=81=E4=B8=A4?= =?UTF-8?q?=E6=AC=A1=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 36 ++++++++------- tests/Material/Count.php | 8 ++++ tests/Test/Fixer/TestScene.php | 67 ++++++++++++++++++++++++++++ tests/Test/TestValidateSceneNext.php | 42 ++++++++++++++++- 4 files changed, 135 insertions(+), 18 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 795745e..53dd4be 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -163,7 +163,7 @@ class Validate extends RuleManager $this->handleEvent($data, 'beforeValidate'); $events = $this->events; $this->events = []; - $rule = $this->getCheckRules($this->getSceneRules()); + $rule = $this->getSceneRules(); $data = $this->pass($data, $rule); $this->events = $events; $this->handleEvent($data, 'afterValidate'); @@ -184,27 +184,33 @@ class Validate extends RuleManager /** * Perform data validation and processing * - * @param array $data Data to be verified - * @param array $rule Rules for validation + * @param array $data Data to be verified + * @param array $rules Rules for validation * @return array * @throws ValidateException * @throws ValidationException */ - private function pass(array $data, array $rule): array + private function pass(array $data, array $rules): array { $this->defaults = array_merge($this->default, $this->defaults); $this->filters = array_merge($this->filter, $this->filters); + // Validated fields are not re-validated + $checkFields = array_diff(array_keys($rules), $this->validateFields); + $checkRules = array_intersect_key($rules, array_flip($checkFields)); + $checkRules = $this->getCheckRules($checkRules); + $this->validateFields = array_merge($this->validateFields, $checkFields); + if ($this->filled) { - $rule = $this->addFilledRule($rule); + $checkRules = $this->addFilledRule($checkRules); } if ($this->bail) { - $rule = $this->addBailRule($rule); + $checkRules = $this->addBailRule($checkRules); } // Defaults and filters only handle the fields that are being validated now - $fields = array_keys($rule); + $fields = array_keys($checkRules); $data = $this->handleDefault($data, $fields); if ($this->eventPriority) { @@ -215,9 +221,10 @@ class Validate extends RuleManager $this->handleEvent($data, 'beforeValidate'); } - if (!empty($rule)) { - $data = $this->getValidationFactory()->make($data, $rule, $this->message, $this->customAttributes)->validate(); + if (!empty($checkRules)) { + $data = $this->getValidationFactory()->make($data, $checkRules, $this->message, $this->customAttributes)->validate(); } + $data = array_merge($this->validatedData, $data); if ($this->eventPriority) { @@ -294,7 +301,7 @@ class Validate extends RuleManager if (isset($sceneRule['next']) && !empty($sceneRule['next'])) { $next = $sceneRule['next']; unset($sceneRule['next']); - $rules = $this->getCheckRules(array_intersect_key($this->rule, array_flip($sceneRule))); + $rules = array_intersect_key($this->rule, array_flip($sceneRule)); return $this->next($next, $rules, $sceneName); } else { return array_intersect_key($this->rule, array_flip($sceneRule)); @@ -321,13 +328,8 @@ class Validate extends RuleManager } // Pre-validation - // Validated fields are not re-validated - $checkFields = array_diff(array_keys($rules), $this->validateFields); - $checkRules = array_intersect_key($rules, array_flip($checkFields)); - $checkRules = $this->getCheckRules($checkRules); - $data = $this->pass($this->checkData, $checkRules); - $this->validateFields = array_merge($this->validateFields, $checkFields); - $this->validatedData = array_merge($this->validatedData, $data); + $data = $this->pass($this->checkData, $rules); + $this->validatedData = array_merge($this->validatedData, $data); // If a scene selector exists if (method_exists($this, lcfirst($next) . 'Selector')) { diff --git a/tests/Material/Count.php b/tests/Material/Count.php index 7596798..a240c22 100644 --- a/tests/Material/Count.php +++ b/tests/Material/Count.php @@ -12,6 +12,8 @@ namespace W7\Tests\Material; +use PHPUnit\Framework\Assert; + class Count { private static $count; @@ -45,4 +47,10 @@ class Count { return self::value($name, ...$arguments); } + + public static function assertEquals($expected, string $name, string $message = '', float $delta = 0.0, int $maxDepth = 10, bool $canonicalize = false, bool $ignoreCase = false) + { + $actual = static::value($name); + Assert::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase); + } } diff --git a/tests/Test/Fixer/TestScene.php b/tests/Test/Fixer/TestScene.php index f66a187..5f12bdb 100644 --- a/tests/Test/Fixer/TestScene.php +++ b/tests/Test/Fixer/TestScene.php @@ -13,6 +13,7 @@ namespace W7\Tests\Test\Fixer; use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\Count; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; @@ -20,6 +21,7 @@ use W7\Validate\Validate; class TestScene extends BaseTestValidate { /** + * @test 测试在场景中获取当前验证数据为空的问题 * @see https://gitee.com/we7coreteam/w7-engine-validate/pulls/5 * @throws ValidateException */ @@ -48,6 +50,7 @@ class TestScene extends BaseTestValidate } /** + * @test 测试场景中添加字段 * @see https://gitee.com/we7coreteam/w7-engine-validate/pulls/3 * @see https://gitee.com/we7coreteam/w7-engine-validate/pulls/6 * @throws ValidateException @@ -100,4 +103,68 @@ class TestScene extends BaseTestValidate $this->assertEmpty(array_diff_key($data, array_flip(['a', 'b', 'c']))); } + + /** + * @test 测试在next场景中,如果返回空场景名导致的问题 + * @see https://gitee.com/we7coreteam/w7-engine-validate/commit/db5ba9de603ac9e167fd46d2b90826595060813b + * @throws ValidateException + */ + public function testNextSceneIsEmpty() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'required' + ]; + + protected $scene = [ + 'testA' => ['a', 'next' => 'test'], + ]; + + protected function testSelector(): string + { + Count::incremental('emptyScene'); + return ''; + } + }; + + $data = $v->scene('testA')->check(['a' => 1]); + $this->assertEquals(1, Count::value('emptyScene')); + $this->assertEquals(1, $data['a']); + } + + /** + * @test 测试在next中规则为原始规则的BUG + * @see https://gitee.com/we7coreteam/w7-engine-validate/commit/f0cefc381e3dd90a8faf69514eb6a2d6016ede77 + * @throws ValidateException + */ + public function testRulesAreNotParsedForNext() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'required|numeric|min:1|test', + 'b' => 'required|numeric|min:1', + ]; + + protected $scene = [ + 'testA' => ['a', 'next' => 'testNext'], + 'testNext' => ['a', 'b'] + ]; + + protected function sceneTestB(ValidateScene $scene) + { + $scene->only(['a'])->next('testNext'); + } + + protected function ruleTest() + { + return true; + } + }; + + $data = $v->scene('testA')->check(['a' => 2, 'b' => 3]); + $this->assertEquals(2, $data['a']); + + $data = $v->scene('testB')->check(['a' => 2, 'b' => 3]); + $this->assertEquals(2, $data['a']); + } } diff --git a/tests/Test/TestValidateSceneNext.php b/tests/Test/TestValidateSceneNext.php index a9fd170..b552413 100644 --- a/tests/Test/TestValidateSceneNext.php +++ b/tests/Test/TestValidateSceneNext.php @@ -13,6 +13,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\Count; use W7\Validate\Exception\ValidateException; use W7\Validate\Validate; @@ -49,7 +50,7 @@ class TestValidateSceneNext extends BaseTestValidate 'testE' => ['h', 'i'], ]; - protected function checkCodeSelector(array $data) + protected function checkCodeSelector(): string { return 'testD'; } @@ -71,4 +72,43 @@ class TestValidateSceneNext extends BaseTestValidate $this->assertCount(9, $data); } + + /** + * @test 测试多个场景指定了同一个字段,是否在一个验证链中,只验证一次 + * @throws ValidateException + */ + public function testNextValidationCountIsOnce() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'required|tests' + ]; + + protected $scene = [ + 'testA' => ['a', 'next' => 'testB'], + 'testB' => ['a', 'next' => 'testC'], + 'testC' => ['a'] + ]; + + protected function ruleTests() + { + Count::incremental('ruleTest'); + return true; + } + }; + + $data = $v->scene('testA')->check(['a' => 1]); + $this->assertEquals(1, $data['a']); + Count::assertEquals(1, 'ruleTest'); + + Count::reset('ruleTest'); + $data = $v->scene('testB')->check(['a' => 1]); + $this->assertEquals(1, $data['a']); + Count::assertEquals(1, 'ruleTest'); + + Count::reset('ruleTest'); + $data = $v->scene('testC')->check(['a' => 1]); + $this->assertEquals(1, $data['a']); + Count::assertEquals(1, 'ruleTest'); + } } -- Gitee From 1e35f73e562ddf407b4c592f2731486a627d4636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 15 Jul 2021 18:33:42 +0800 Subject: [PATCH 115/152] =?UTF-8?q?[A]=20=E9=BB=98=E8=AE=A4=E5=80=BC?= =?UTF-8?q?=E5=92=8C=E8=BF=87=E6=BB=A4=E5=99=A8=E5=A2=9E=E5=8A=A0=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E5=AD=97=E6=AE=B5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/DataAttribute.php | 22 +++++++++++ src/Validate.php | 31 +++++++++++----- tests/Test/TestDataDefault.php | 67 +++++++++++++++++++++++----------- tests/Test/TestDataFilter.php | 32 ++++++++++++++-- 4 files changed, 119 insertions(+), 33 deletions(-) create mode 100644 src/Support/DataAttribute.php diff --git a/src/Support/DataAttribute.php b/src/Support/DataAttribute.php new file mode 100644 index 0000000..dcff6cc --- /dev/null +++ b/src/Support/DataAttribute.php @@ -0,0 +1,22 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Support; + +class DataAttribute +{ + /** + * Whether to delete the field in the check data + * @var bool + */ + public $deleteField = false; +} diff --git a/src/Validate.php b/src/Validate.php index 53dd4be..9c428bb 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -23,6 +23,7 @@ use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\Concerns\DefaultInterface; use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Concerns\MessageProviderInterface; +use W7\Validate\Support\DataAttribute; use W7\Validate\Support\Event\ValidateEventAbstract; use W7\Validate\Support\MessageProvider; use W7\Validate\Support\Storage\ValidateCollection; @@ -467,21 +468,26 @@ class Validate extends RuleManager if (!$data->has($field)) { return; } - $value = $data->get($field); + $value = $data->get($field); + $dataAttribute = new DataAttribute(); if (is_callable($callback)) { $value = call_user_func($callback, $value); } elseif ((is_string($callback) || is_object($callback)) && class_exists($callback) && is_subclass_of($callback, FilterInterface::class)) { /** @var FilterInterface $filter */ - $filter = new $callback; + $filter = new $callback($dataAttribute); $value = $filter->handle($value); } elseif (is_string($callback) && method_exists($this, 'filter' . ucfirst($callback))) { - $value = call_user_func([$this, 'filter' . ucfirst($callback)], $value); + $value = call_user_func([$this, 'filter' . ucfirst($callback)], $value, $dataAttribute); } else { throw new ValidateRuntimeException('The provided filter is wrong'); } - $data->set($field, $value); + if (true === $dataAttribute->deleteField) { + $data->forget($field); + } else { + $data->set($field, $value); + } } /** @@ -528,21 +534,28 @@ class Validate extends RuleManager $isEmpty = function ($value) { return null === $value || [] === $value || '' === $value; }; - $value = $data->get($field); + $value = $data->get($field); + $dataAttribute = new DataAttribute(); + if ($isEmpty($value) || true === $any) { if (is_callable($callback)) { - $value = call_user_func($callback, $value, $field, $this->checkData); + $value = call_user_func($callback, $value, $field, $this->checkData, $dataAttribute); } elseif ((is_string($callback) || is_object($callback)) && class_exists($callback) && is_subclass_of($callback, DefaultInterface::class)) { /** @var DefaultInterface $default */ - $default = new $callback(); + $default = new $callback($dataAttribute); $value = $default->handle($value, $field, $this->checkData); } elseif (is_string($callback) && method_exists($this, 'default' . ucfirst($callback))) { - $value = call_user_func([$this, 'default' . ucfirst($callback)], $value, $field, $this->checkData); + $value = call_user_func([$this, 'default' . ucfirst($callback)], $value, $field, $this->checkData, $dataAttribute); } else { $value = $callback; } } - $data->set($field, $value); + + if (true === $dataAttribute->deleteField) { + $data->forget($field); + } else { + $data->set($field, $value); + } } /** diff --git a/tests/Test/TestDataDefault.php b/tests/Test/TestDataDefault.php index 3de1a52..75d147a 100644 --- a/tests/Test/TestDataDefault.php +++ b/tests/Test/TestDataDefault.php @@ -15,15 +15,16 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Concerns\DefaultInterface; +use W7\Validate\Support\DataAttribute; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; class SetDefaultIsHello implements DefaultInterface { - public function handle($value, string $attribute, array $originalData) - { - return "Hello"; - } + public function handle($value, string $attribute, array $originalData) + { + return 'Hello'; + } } class TestDataDefault extends BaseTestValidate @@ -42,7 +43,7 @@ class TestDataDefault extends BaseTestValidate $data = $v->check([]); - $this->assertEquals('123', $data['name']); + $this->assertSame('123', $data['name']); } public function testDefaultIsArray() @@ -156,7 +157,7 @@ class TestDataDefault extends BaseTestValidate $v->check([]); $data = $v->scene('test')->check([]); - $this->assertEquals('小张', $data['name']); + $this->assertSame('小张', $data['name']); } public function testCancelDefaultValue() @@ -185,19 +186,43 @@ class TestDataDefault extends BaseTestValidate } public function testDefaultUseDefaultClass() - { - $v = new class extends Validate - { - protected $rule = [ - 'name' => '' - ]; - - protected $default = [ - 'name' => SetDefaultIsHello::class - ]; - }; - - $data = $v->check([]); - $this->assertEquals("Hello", $data['name']); - } + { + $v = new class extends Validate { + protected $rule = [ + 'name' => '' + ]; + + protected $default = [ + 'name' => SetDefaultIsHello::class + ]; + }; + + $data = $v->check([]); + $this->assertSame('Hello', $data['name']); + } + + public function testDefaultDeleteField() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'numeric' + ]; + + protected $default = [ + 'a' => ['value' => 'deleteField', 'any' => true] + ]; + + public function defaultDeleteField($value, $field, $data, DataAttribute $dataAttribute) + { + $dataAttribute->deleteField = true; + return ''; + } + }; + + $data = $v->check([ + 'a' => 123 + ]); + + $this->assertTrue(empty($data)); + } } diff --git a/tests/Test/TestDataFilter.php b/tests/Test/TestDataFilter.php index 9050c7f..150ab90 100644 --- a/tests/Test/TestDataFilter.php +++ b/tests/Test/TestDataFilter.php @@ -14,6 +14,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Support\Concerns\FilterInterface; +use W7\Validate\Support\DataAttribute; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; @@ -99,7 +100,7 @@ class TestDataFilter extends BaseTestValidate $data = $v->check(['id' => ['1', '2', 3, '4']]); foreach ($data['id'] as $id) { - $this->assertEquals('integer', gettype($id)); + $this->assertSame('integer', gettype($id)); } } @@ -138,8 +139,33 @@ class TestDataFilter extends BaseTestValidate }; $data = $v->check(['id' => '你好']); - $this->assertEquals(0, $data['id']); + $this->assertSame(0, $data['id']); $data = $v->scene('test')->check(['id' => '你好']); - $this->assertEquals('你好', $data['id']); + $this->assertSame('你好', $data['id']); + } + + public function testFilterDeleteField() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => '' + ]; + + protected $filter = [ + 'a' => 'deleteField' + ]; + + public function filterDeleteField($value, DataAttribute $dataAttribute) + { + $dataAttribute->deleteField = true; + return ''; + } + }; + + $data = $v->check([ + 'a' => 123 + ]); + + $this->assertTrue(empty($data)); } } -- Gitee From 7fb7132456e01dd6af684182d0dc9fa5986c1456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 27 Aug 2021 18:21:17 +0800 Subject: [PATCH 116/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E8=A7=84=E5=88=99=E4=BC=9A=E5=87=BA=E7=8E=B0=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E7=A9=BA=E8=A7=84=E5=88=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/RuleManagerScene.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php index 3fd2a47..373d9b4 100644 --- a/src/Support/RuleManagerScene.php +++ b/src/Support/RuleManagerScene.php @@ -48,7 +48,9 @@ class RuleManagerScene implements SceneInterface public function append(string $field, $rules): SceneInterface { if (isset($this->checkRules[$field])) { - if (!is_array($this->checkRules[$field])) { + if (empty($this->checkRules[$field])) { + $this->checkRules[$field] = []; + } elseif (!is_array($this->checkRules[$field])) { $this->checkRules[$field] = explode('|', $this->checkRules[$field]); } -- Gitee From edff96262630126dc15c377fa7efe3abceeb0168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 27 Aug 2021 19:02:14 +0800 Subject: [PATCH 117/152] =?UTF-8?q?[D]=20=E5=88=A0=E9=99=A4=E5=8D=95?= =?UTF-8?q?=E5=85=83=E6=B5=8B=E8=AF=95=E4=B8=AD=E6=97=A0=E7=94=A8=E7=9A=84?= =?UTF-8?q?Use?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Test/TestHandlerFunction.php | 75 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/tests/Test/TestHandlerFunction.php b/tests/Test/TestHandlerFunction.php index 6a4e224..23cc807 100644 --- a/tests/Test/TestHandlerFunction.php +++ b/tests/Test/TestHandlerFunction.php @@ -12,55 +12,58 @@ namespace W7\Tests\Test; -use W7\Tests\Material\HandlerDataValidate; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; use W7\Validate\Validate; class TestHandlerFunction extends BaseTestValidate { - public function testAfterFunction(){ - $v = new class extends Validate{ - protected $rule = [ - 'id' => 'required' - ]; + public function testAfterFunction() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required' + ]; - protected $scene = [ - 'testAfter' => ['id','after' => 'checkId'] - ]; + protected $scene = [ + 'testAfter' => ['id', 'after' => 'checkId'] + ]; - protected function afterCheckId($data){ - if ($data['id'] < 0){ - return "ID错误"; - } - return true; - } - }; + protected function afterCheckId($data) + { + if ($data['id'] < 0) { + return 'ID错误'; + } + return true; + } + }; - $this->expectException(ValidateException::class); - $this->expectExceptionMessage("ID错误"); + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('ID错误'); - $v->scene("testAfter")->check(['id' => -1]); - } + $v->scene('testAfter')->check(['id' => -1]); + } - public function testBeforeFunction(){ - $v = new class extends Validate{ - protected $rule = [ - 'id' => 'required' - ]; + public function testBeforeFunction() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required' + ]; - protected $scene = [ - 'testBefore' => ['id','before' => 'checkSiteStatus'] - ]; + protected $scene = [ + 'testBefore' => ['id', 'before' => 'checkSiteStatus'] + ]; - protected function beforeCheckSiteStatus(array $data){ - return "站点未开启"; - } - }; + protected function beforeCheckSiteStatus(array $data) + { + return '站点未开启'; + } + }; - $this->expectException(ValidateException::class); - $this->expectExceptionMessage("站点未开启"); + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('站点未开启'); - $v->scene("testBefore")->check([]); - } + $v->scene('testBefore')->check([]); + } } -- Gitee From 81c1a5f61c6c57d512d8348e9a7ddcb14a0fcab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 27 Aug 2021 19:19:24 +0800 Subject: [PATCH 118/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 10 ++++++++++ src/Support/Concerns/SceneInterface.php | 5 +++++ src/Support/Rule/BaseRule.php | 5 +++++ src/Support/RuleManagerScene.php | 5 +++++ src/Support/Storage/ValidateCollection.php | 10 ++++++++++ src/Support/Storage/ValidateConfig.php | 2 ++ src/Support/ValidateScene.php | 14 ++++++++++++-- src/Validate.php | 20 ++++++++++++++++++++ 8 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index b851c78..e256dbd 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -19,16 +19,23 @@ use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\RuleManagerScene; use W7\Validate\Support\Storage\ValidateConfig; +/** + * @link https://v.neww7.com/en/3/RuleManager.html#introduction + */ class RuleManager { /** * All original validation rules + * + * @link https://v.neww7.com/en/3/Validate.html#rule * @var array */ protected $rule = []; /** * Define a scenario for the validation rule + * + * @link https://v.neww7.com/en/3/Validate.html#scene * @var array */ protected $scene = []; @@ -43,18 +50,21 @@ class RuleManager /** * The array of custom error messages. * + * @link https://v.neww7.com/en/3/Validate.html#message * @var array */ protected $message = []; /** * Current validate scene + * * @var string|null */ private $currentScene = null; /** * Extension method name + * * @var array */ private static $extendName = []; diff --git a/src/Support/Concerns/SceneInterface.php b/src/Support/Concerns/SceneInterface.php index 5be48eb..b4d649e 100644 --- a/src/Support/Concerns/SceneInterface.php +++ b/src/Support/Concerns/SceneInterface.php @@ -17,6 +17,7 @@ interface SceneInterface /** * Specify the list of fields to be validated * + * @link https://v.neww7.com/en/3/Scene.html#only * @param array $fields * @return $this */ @@ -25,6 +26,7 @@ interface SceneInterface /** * Adding a validation rule for a field * + * @link https://v.neww7.com/en/3/Scene.html#append * @param string $field * @param string|array $rules * @return $this @@ -34,6 +36,7 @@ interface SceneInterface /** * Remove the validation rule for a field * + * @link https://v.neww7.com/en/3/Scene.html#remove * @param string $field * @param array|string|null $rule Validate rules.if $rule is null,remove all rules from the current field * @return $this @@ -43,6 +46,7 @@ interface SceneInterface /** * Add fields to the validation list * + * @link https://v.neww7.com/en/3/Scene.html#appendcheckfield * @param string $field * @return $this */ @@ -51,6 +55,7 @@ interface SceneInterface /** * Delete fields from the validation list * + * @link https://v.neww7.com/en/3/Scene.html#removecheckfield * @param string $field * @return $this */ diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index e56f852..bfcd49b 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -12,6 +12,11 @@ namespace W7\Validate\Support\Rule; +/** + * Custom Rules + * + * @link https://v.neww7.com/en/3/Rule.html#using-rule-objects + */ abstract class BaseRule implements RuleInterface { /** diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php index 373d9b4..e02b9cb 100644 --- a/src/Support/RuleManagerScene.php +++ b/src/Support/RuleManagerScene.php @@ -14,6 +14,11 @@ namespace W7\Validate\Support; use W7\Validate\Support\Concerns\SceneInterface; +/** + * Scene classes for rule managers + * + * @link https://v.neww7.com/en/3/Scene.html#methods-of-the-scene-class + */ class RuleManagerScene implements SceneInterface { /** diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 7d6576c..0687be4 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -19,11 +19,17 @@ use Illuminate\Support\Collection; use Illuminate\Support\HigherOrderWhenProxy; use Illuminate\Support\Str; +/** + * Validator collection is a subclass of Illuminate\Support\Collection + * + * @link https://v.neww7.com/en/3/Collection.html#description + */ class ValidateCollection extends Collection { /** * Determine if an item exists in the collection by key. * + * @link https://v.neww7.com/en/3/Collection.html#has * @param mixed $key * @return bool */ @@ -43,6 +49,7 @@ class ValidateCollection extends Collection /** * Execute when the specified field exists * + * @link https://v.neww7.com/en/3/Collection.html#whenhas * @param mixed $key Fields to be validated * @param callable $callback Methods of execution * @param callable|null $default Methods to execute when not present @@ -56,6 +63,7 @@ class ValidateCollection extends Collection /** * Execute when the specified field does not exist * + * @link https://v.neww7.com/en/3/Collection.html#whennothas * @param mixed $key Fields to be validated * @param callable $callback Methods to execute when not present * @param callable|null $default Methods of execution @@ -69,6 +77,7 @@ class ValidateCollection extends Collection /** * Get an item from the collection by key. * + * @link https://v.neww7.com/en/3/Collection.html#get * @param mixed $key Field Name * @param mixed|Closure|null $default Default Value * @return array|ArrayAccess|mixed @@ -123,6 +132,7 @@ class ValidateCollection extends Collection /** * Write the specified value in the collection * + * @link https://v.neww7.com/en/3/Collection.html#set * @param mixed $key * @param mixed $value * @return $this diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 3f1c62a..eef17d5 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -67,6 +67,7 @@ final class ValidateConfig /** * Provide validator factory * + * @link https://v.neww7.com/en/3/Start.html#configuration-validator-factory * @param Factory $factory * @return ValidateConfig */ @@ -175,6 +176,7 @@ final class ValidateConfig /** * Set the custom rules namespace prefix, If more than one exists, they all take effect * + * @link https://v.neww7.com/en/3/Rule.html#pre-processing * @param string $rulesPath Custom rules namespace prefixes * @return $this */ diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 6a10d61..2dc008f 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -21,9 +21,10 @@ use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\Storage\ValidateCollection; /** - * Class ValidateScene - * @package W7\Validate\Support + * Scene classes for validators * + * @link https://v.neww7.com/en/3/Scene.html#methods-of-the-scene-class + * @package W7\Validate\Support * @property-read array $events Events to be processed for this validate * @property-read array $befores Methods to be executed before this validate * @property-read array $afters Methods to be executed after this validate @@ -96,6 +97,7 @@ class ValidateScene extends RuleManagerScene /** * Add conditions to a given field based on a Closure. * + * @link https://v.neww7.com/en/3/Scene.html#sometimes * @param string|string[] $attribute field name * @param string|array|BaseRule $rules rules * @param callable $callback Closure,method provides a {@see ValidateCollection} $data parameter, @@ -126,6 +128,7 @@ class ValidateScene extends RuleManagerScene /** * Join the event * + * @link https://v.neww7.com/en/3/Scene.html#event * @param string $handler Full class name of the event, full namespace string or add ::class * @param mixed ...$params Parameters to be passed to the event * @return $this @@ -139,6 +142,7 @@ class ValidateScene extends RuleManagerScene /** * Add a method that needs to be executed before validation * + * @link https://v.neww7.com/en/3/Scene.html#before * @param string $callbackName Validate the method name in the class * @param mixed ...$params Parameters to be passed to the method * @return $this @@ -152,6 +156,7 @@ class ValidateScene extends RuleManagerScene /** * Add a method that needs to be executed after validation * + * @link https://v.neww7.com/en/3/Scene.html#after * @param string $callbackName Validate the method name in the class * @param mixed ...$params Parameters to be passed to the method * @return $this @@ -165,6 +170,7 @@ class ValidateScene extends RuleManagerScene /** * Set a default value for the specified field * + * @link https://v.neww7.com/en/3/Scene.html#default * @param string $field Name of the data field to be processed * @param callable|Closure|mixed|DefaultInterface|null $callback The default value or an anonymous function that returns the default value which will * be assigned to the attributes being validated if they are empty. The signature of the anonymous function @@ -198,6 +204,7 @@ class ValidateScene extends RuleManagerScene /** * Set a filter for the specified field * + * @link https://v.neww7.com/en/3/Scene.html#filter * Filter is a data processor. * It invokes the specified filter callback to process the attribute value * and save the processed value back to the attribute. @@ -236,6 +243,7 @@ class ValidateScene extends RuleManagerScene /** * Specify the next scene or next scene selector * + * @link https://v.neww7.com/en/3/Scene.html#next * @param string $name * @return $this */ @@ -260,6 +268,7 @@ class ValidateScene extends RuleManagerScene /** * Get the current validation data * + * @link https://v.neww7.com/en/3/Scene.html#getdata * @param string $key * @param mixed $default * @return array|mixed @@ -275,6 +284,7 @@ class ValidateScene extends RuleManagerScene /** * Get the current validation data,Return the {@see ValidateCollection} type * + * @link https://v.neww7.com/en/3/Scene.html#getvalidatedata * @return ValidateCollection */ public function getValidateData(): ValidateCollection diff --git a/src/Validate.php b/src/Validate.php index 9c428bb..4553b80 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -34,90 +34,110 @@ class Validate extends RuleManager { /** * Global Event Handler + * + * @link https://v.neww7.com/en/3/Validate.html#event * @var array */ protected $event = []; /** * Whether to stop running after the first verification failure + * + * @link https://v.neww7.com/en/3/Validate.html#bail * @var bool */ protected $bail = true; /** * All validated fields cannot be empty when present + * + * @link https://v.neww7.com/en/3/Validate.html#filled * @var bool */ protected $filled = true; /** * The filter. This can be a global function name, anonymous function, etc. + * + * @link https://v.neww7.com/en/3/Validate.html#filter * @var array */ protected $filter = []; /** * Sets the specified property to the specified default value. + * + * @link https://v.neww7.com/en/3/Validate.html#default * @var array */ protected $default = []; /** * Event Priority + * * @var bool */ private $eventPriority = true; /** * Events to be processed for this validate + * * @var array */ private $events = []; /** * Methods to be executed before this validate + * * @var array */ private $befores = []; /** * Methods to be executed after this validate + * * @var array */ private $afters = []; /** * This validation requires a default value for the value + * * @var array */ private $defaults = []; /** * Filters to be passed for this validation + * * @var array */ private $filters = []; /** * Error Message Provider + * * @var MessageProviderInterface */ private $messageProvider = null; /** * Data to be validated + * * @var array */ private $checkData = []; /** * Data validated this time + * * @var array */ private $validatedData = []; /** * Fields validated this time + * * @var array */ private $validateFields = []; -- Gitee From 48cf9cb1e84ad679b33c29902dc68ef6b7a4da44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 2 Sep 2021 19:49:17 +0800 Subject: [PATCH 119/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E7=9B=B8=E5=85=B3=E7=9A=84?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- tests/Material/HandlerEventValidate.php | 43 ------ tests/Test/TestCustomRuleAndMessage.php | 183 ++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 44 deletions(-) delete mode 100644 tests/Material/HandlerEventValidate.php create mode 100644 tests/Test/TestCustomRuleAndMessage.php diff --git a/composer.json b/composer.json index accc636..511966c 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "form validate" ], "require": { - "php": "^7.2.5|^8.0", + "php": "^7.2.5|^8.0|^8.1", "illuminate/validation": "^6.0|^7.0|^8.0" }, "require-dev": { diff --git a/tests/Material/HandlerEventValidate.php b/tests/Material/HandlerEventValidate.php deleted file mode 100644 index 09de3f6..0000000 --- a/tests/Material/HandlerEventValidate.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Tests\Material; - -use W7\Tests\Material\Event\Increasing; -use W7\Tests\Material\Event\SetDefault; -use W7\Validate\Validate; - -class HandlerEventValidate extends Validate -{ - protected $rule = [ - 'a' => 'required', - 'b' => 'required', - 'i' => 'required|numeric' - ]; - - protected $scene = [ - 'setDefault' => ['a', 'b', 'handler' => [ - SetDefault::class => [[ - 'a' => 1, - 'b' => 2 - ]] - ]], - - 'incr' => ['i', 'handler' => [ - Increasing::class => 'i' - ]], - - 'useIncr' => [ - 'use' => 'incr' - ] - ]; -} diff --git a/tests/Test/TestCustomRuleAndMessage.php b/tests/Test/TestCustomRuleAndMessage.php new file mode 100644 index 0000000..27b47b5 --- /dev/null +++ b/tests/Test/TestCustomRuleAndMessage.php @@ -0,0 +1,183 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use Illuminate\Support\Arr; +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Exception\ValidateException; +use W7\Validate\Support\ValidateScene; +use W7\Validate\Validate; + +class TestCustomRuleA extends Validate +{ + protected $rule = [ + 'num' => 'numberIsTen' + ]; + + protected $message = [ + 'num.numberIsTen' => '给定的参数不是10' + ]; + + protected function ruleNumberIsTen($att, $value): bool + { + return 10 === (int)$value; + } +} + +class TestCustomRuleB extends TestCustomRuleA +{ + protected $message = [ + 'num.numberIsTen' => '给定的参数不是十' + ]; + + protected function ruleNumberIsTen($att, $value): bool + { + return '十' === (string)$value; + } +} + +class TestExtendRule extends Validate +{ + public function __construct() + { + self::extend('mobile', function ($attribute, $value) { + return is_scalar($value) && 1 === preg_match('/^1[3-9]\d{9}$/', (string)$value); + }, ':attribute不是有效的手机号码'); + } + + protected $rule = [ + 'bind' => 'mobile' + ]; + + protected $customAttributes = [ + 'bind' => '绑定手机号' + ]; + + protected function sceneReplacerMobileMessage(ValidateScene $scene) + { + $scene->only(['bind']); + self::replacer('mobile', function ($message, $attribute, $rule, $parameters) { + return ($this->customAttributes[$attribute] ?? $attribute) . '是错误的手机号码'; + }); + } +} + +class TestImplicitRule extends Validate +{ + public function __construct() + { + self::extendImplicit('isNotEmpty', function ($attribute, $value) { + return !empty($value); + }, '给定的值为空'); + } + + protected $rule = [ + 'content' => 'isNotEmpty' + ]; +} + +class TestDependentRule extends Validate +{ + public function __construct() + { + self::extendDependent('contains', function ($attribute, $value, $parameters, $validator) { + return str_contains($value, Arr::get($validator->getData(), $parameters[0])); + }, '不支持该域的邮箱'); + } + + protected $rule = [ + '*.email' => 'contains:*.provider' + ]; +} + +class TestCustomRuleAndMessage extends BaseTestValidate +{ + /** + * @test 测试依赖规则 + * + * @throws ValidateException + */ + public function testDependentRule() + { + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('不支持该域的邮箱'); + + TestDependentRule::make()->check([ + ['email' => '995645888@qq.com', 'provider' => 'qq.com'], + ['email' => '351409246@qq.com', 'provider' => 'qq.com'], + ['email' => 'admin@itwmw.com', 'provider' => 'qq.com'] + ]); + } + + /** + * @test 测试当值为空,规则也依旧执行 + * @throws ValidateException + */ + public function testImplicitRule() + { + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('给定的值为空'); + TestImplicitRule::make()->check([]); + } + + /** + * @test 测试扩展规则和对应的错误消息是否生效 + * @throws ValidateException + */ + public function testExtendRule() + { + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('绑定手机号不是有效的手机号码'); + TestExtendRule::make()->check([ + 'bind' => 123 + ]); + } + + /** + * @test 测试修改扩展规则对应的错误消息 + * @throws ValidateException + */ + public function testReplacerErrorMessage() + { + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('绑定手机号是错误的手机号码'); + TestExtendRule::make()->scene('replacerMobileMessage')->check([ + 'bind' => 123 + ]); + } + + /** + * @test 测试多个验证器定义相同的规则名,规则是否会冲突 + */ + public function testSameNameRule() + { + try { + $data = TestCustomRuleA::make()->check([ + 'num' => 0 + ]); + } catch (ValidateException $e) { + $this->assertSame('给定的参数不是10', $e->getMessage(), '返回的错误消息不符合预期'); + } + $this->assertFalse(isset($data), '验证错误的通过'); + + try { + $data = TestCustomRuleB::make()->check([ + 'num' => 10 + ]); + } catch (ValidateException $e) { + $this->assertSame('给定的参数不是十', $e->getMessage(), '返回的错误消息不符合预期'); + } + + $this->assertFalse(isset($data), '验证错误的通过'); + } +} -- Gitee From 1c520b182e644fee484a658af0f267bfe3ea002d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 3 Sep 2021 11:25:20 +0800 Subject: [PATCH 120/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=A2=84?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E6=AD=A3=E5=88=99=E8=A1=A8=E8=BE=BE=E5=BC=8F?= =?UTF-8?q?=20[F]=20=E4=BF=AE=E5=A4=8D=E5=90=8C=E4=B8=80=E4=BC=9A=E8=AF=9D?= =?UTF-8?q?=E4=B8=8B=EF=BC=8C=E4=B8=8D=E5=90=8C=E7=9A=84=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E5=99=A8=E6=B3=A8=E5=86=8C=E7=9B=B8=E5=90=8C=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E8=87=AA=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E5=8F=AA=E7=94=9F=E6=95=88=E4=B8=80=E4=B8=AA=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20[F]=20=E4=BF=AE=E5=A4=8D=E9=AA=8C=E8=AF=81=E5=99=A8?= =?UTF-8?q?=E8=A7=84=E5=88=99=E6=97=A0=E6=B3=95=E4=BD=BF=E7=94=A8=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 42 +++++++++--- tests/Test/TestRegexRule.php | 123 +++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 8 deletions(-) create mode 100644 tests/Test/TestRegexRule.php diff --git a/src/RuleManager.php b/src/RuleManager.php index e256dbd..dc95a62 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -55,6 +55,13 @@ class RuleManager */ protected $message = []; + /** + * Regular validation rules + * + * @var array + */ + protected $regex = []; + /** * Current validate scene * @@ -62,6 +69,13 @@ class RuleManager */ private $currentScene = null; + /** + * Rules for using regular expressions for validation + * + * @var string[] + */ + private $regexRule = ['regex', 'not_regex']; + /** * Extension method name * @@ -74,7 +88,7 @@ class RuleManager * @var array */ private static $implicitRules = []; - + /** * Set current validate scene * @@ -145,6 +159,16 @@ class RuleManager return array_map(function ($ruleName) use ($field) { if (is_string($ruleName)) { + foreach ($this->regexRule as $regexRuleName) { + $regexRuleName = $regexRuleName . ':'; + if (0 === strpos($ruleName, $regexRuleName)) { + $regexName = substr($ruleName, strlen($regexRuleName)); + if (isset($this->regex[$regexName])) { + return $regexRuleName . $this->regex[$regexName]; + } + } + } + $ruleClass = $this->getRuleClass($ruleName); if (false !== $ruleClass) { if (!empty($message = $this->getMessage($field, $ruleName))) { @@ -294,8 +318,8 @@ class RuleManager list($rule, $param) = Common::getKeyAndParam($ruleName, false); // Retrieve the real custom rule method name, and modify the corresponding error message - if (array_key_exists($rule, self::$extendName)) { - $ruleName = md5(get_called_class() . $rule); + $ruleName = md5(get_called_class() . $rule); + if (array_key_exists($rule, self::$extendName) && in_array($ruleName, self::$extendName[$rule])) { // Determine if an error message is defined for a custom rule method if (null !== $field && isset($this->message[$field . '.' . $rule])) { $this->message[$field . '.' . $ruleName] = $this->message[$field . '.' . $rule]; @@ -369,13 +393,15 @@ class RuleManager } } - $ruleName = Common::getKeyAndParam($value)[0]; + if (is_string($value)) { + $ruleName = Common::getKeyAndParam($value)[0]; - if (in_array($ruleName, self::$implicitRules)) { - return 'filled'; + if (in_array($ruleName, self::$implicitRules)) { + return 'filled'; + } } - - return $ruleName; + + return $value; }, $rule); if (empty(array_intersect($conflictRules, $rulesName))) { diff --git a/tests/Test/TestRegexRule.php b/tests/Test/TestRegexRule.php new file mode 100644 index 0000000..d00bc94 --- /dev/null +++ b/tests/Test/TestRegexRule.php @@ -0,0 +1,123 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Exception\ValidateException; +use W7\Validate\Support\ValidateScene; +use W7\Validate\Validate; + +class TestRegexRule extends BaseTestValidate +{ + /** + * @test 测试正则表达式`regex`规则是否可以正常使用 + * @throws ValidateException + */ + public function testRegexRule() + { + $v = new class extends Validate { + protected $regex = [ + 'number' => '/^\d+$/' + ]; + + protected $rule = [ + 'num' => 'required|regex:number' + ]; + + protected $message = [ + 'num.regex' => '给定的值必须是数字' + ]; + }; + + $data = $v->check([ + 'num' => '123' + ]); + $this->assertEquals('123', $data['num']); + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('给定的值必须是数字'); + $v->check([ + 'num' => 'sss' + ]); + } + + /** + * @test 测试正则表达式`not_regex`规则是否可以正常使用 + * @throws ValidateException + */ + public function testNotRegexRule() + { + $v = new class extends Validate { + protected $regex = [ + 'number' => '/^\d+$/' + ]; + + protected $rule = [ + 'user' => 'required|not_regex:number' + ]; + + protected $message = [ + 'user.not_regex' => '给定的值不可以为纯数字' + ]; + }; + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('给定的值不可以为纯数字'); + $v->check([ + 'user' => '123' + ]); + + $data = $v->check([ + 'user' => 'a1b2' + ]); + $this->assertEquals('a1b2', $data['user']); + } + + /** + * @test 测试正则表示式规则在验证场景中的使用 + * @throws ValidateException + */ + public function testRegexRuleInScene() + { + $v = new class extends Validate { + protected $regex = [ + 'status' => '/^0|1|on|off|true|false$/' + ]; + + protected $rule = [ + 'status' => 'required' + ]; + + protected function sceneTest(ValidateScene $scene) + { + $scene->only(['status']) + ->append('status', 'regex:status'); + + $this->setMessages([ + 'status.regex' => '状态不符合要求' + ]); + } + }; + + $data = $v->scene('test')->check([ + 'status' => 1 + ]); + $this->assertSame(1, $data['status']); + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('状态不符合要求'); + $v->scene('test')->check([ + 'status' => 'close' + ]); + } +} -- Gitee From 2e3f05d13e74d3c8eac3e87dca0f0463b8421d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 6 Sep 2021 16:31:06 +0800 Subject: [PATCH 121/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index a9de19c..e2c7659 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,11 @@ # 增强表单验证 +[![star](https://icon.itwmw.com/badge/dynamic/json?label=&query=stargazers_count&url=https%3A%2F%2Fgitee.com%2Fapi%2Fv5%2Frepos%2Fwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Stars&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/stargazers) +[![fork](https://icon.itwmw.com/badge/dynamic/json?label=&query=forks_count&url=https%3A%2F%2Fgitee.com%2Fapi%2Fv5%2Frepos%2Fwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Forks&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/members) +![license](https://icon.itwmw.com/badge/dynamic/json?label=License&query=license&url=https%3A%2F%2Fgitee.com%2Fapi%2Fv5%2Frepos%2Fwe7coreteam%2Fw7-engine-validate%2Flicense) +![Version Support](https://icon.itwmw.com/badge/PHP-%5E7.2.5%7C%5E8.0%7C%5E8.1-brightgreen?logo=php&logoColor=violet) +![Docs](https://icon.itwmw.com/badge/Docs-passing-brightgreen) +![Tests](https://icon.itwmw.com/badge/Tests-100%25%20passed-brightgreen) +![document](https://icon.itwmw.com/packagist/dt/w7/engine-validate?style=social&logo=packagist) ## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 -- Gitee From 48c4ed05d0cb4641d9bb0e974002674e1dcd9df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 6 Sep 2021 17:41:35 +0800 Subject: [PATCH 122/152] =?UTF-8?q?[U]=20=E7=94=B1=E4=BA=8EGitee=E5=AF=B9?= =?UTF-8?q?=E4=BA=8E=E5=BC=80=E6=94=BE=E7=9A=84API=E6=9C=89=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E9=99=90=E6=B5=81=EF=BC=8C=E6=89=80=E4=BB=A5=E6=8D=A2?= =?UTF-8?q?=E4=BA=86=E4=B8=80=E4=B8=AAAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e2c7659..5d91b7d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # 增强表单验证 -[![star](https://icon.itwmw.com/badge/dynamic/json?label=&query=stargazers_count&url=https%3A%2F%2Fgitee.com%2Fapi%2Fv5%2Frepos%2Fwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Stars&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/stargazers) -[![fork](https://icon.itwmw.com/badge/dynamic/json?label=&query=forks_count&url=https%3A%2F%2Fgitee.com%2Fapi%2Fv5%2Frepos%2Fwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Forks&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/members) -![license](https://icon.itwmw.com/badge/dynamic/json?label=License&query=license&url=https%3A%2F%2Fgitee.com%2Fapi%2Fv5%2Frepos%2Fwe7coreteam%2Fw7-engine-validate%2Flicense) +[![star](https://icon.itwmw.com/badge/dynamic/json?label=&query=star&url=https%3A%2F%2Fwww.itwmw.com%2Ftools%2Fgitee.php%3Fname%3Dwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Stars&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/stargazers) +[![fork](https://icon.itwmw.com/badge/dynamic/json?label=&query=fork&url=https%3A%2F%2Fwww.itwmw.com%2Ftools%2Fgitee.php%3Fname%3Dwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Forks&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/members) +![Docs](https://icon.itwmw.com/badge/License-Apache--2.0-blue) ![Version Support](https://icon.itwmw.com/badge/PHP-%5E7.2.5%7C%5E8.0%7C%5E8.1-brightgreen?logo=php&logoColor=violet) -![Docs](https://icon.itwmw.com/badge/Docs-passing-brightgreen) +[![Docs](https://icon.itwmw.com/badge/Docs-passing-brightgreen)](https://v.neww7.com) ![Tests](https://icon.itwmw.com/badge/Tests-100%25%20passed-brightgreen) ![document](https://icon.itwmw.com/packagist/dt/w7/engine-validate?style=social&logo=packagist) ## 介绍 -- Gitee From a70c2b88039ef3225bd9444aa26e4f48a89c0094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 9 Sep 2021 18:24:11 +0800 Subject: [PATCH 123/152] =?UTF-8?q?[A]=20=E5=9C=BA=E6=99=AF=E4=B8=AD?= =?UTF-8?q?=E7=9A=84after=E5=92=8Cbefore=E6=94=AF=E6=8C=81=E9=97=AD?= =?UTF-8?q?=E5=8C=85=E5=92=8Ccallable=20[U]=20=E8=B0=83=E6=95=B4=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E6=97=B6=E7=9A=84=E5=BC=82=E5=B8=B8=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E4=B8=BAValidateRuntimeException?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + README.md | 6 +- composer.json | 2 +- phpunit.xml | 25 +++++++- src/Support/ValidateScene.php | 12 ++-- src/Validate.php | 19 +++--- tests/Test/TestCustomMessageProvider.php | 43 ++++++++++++++ tests/Test/TestCustomRuleAndMessage.php | 52 +++++++++++++++- tests/Test/TestDataFilter.php | 41 +++++++++++++ tests/Test/TestHandlerEvent.php | 62 +++++++++++++++++++ tests/Test/TestHandlerFunction.php | 16 +++++ tests/Test/TestValidateMessage.php | 76 +++++++++++++++++++++++- tests/Test/TestValidateScene.php | 20 +++++++ tests/Test/TestValidateSceneNext.php | 48 +++++++++++++++ 14 files changed, 400 insertions(+), 24 deletions(-) create mode 100644 tests/Test/TestCustomMessageProvider.php diff --git a/.gitignore b/.gitignore index e6979f2..76a4098 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ runtime/ /vendor /.idea /composer.lock +/coverage/ +/cache/ diff --git a/README.md b/README.md index 5d91b7d..deabd30 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # 增强表单验证 -[![star](https://icon.itwmw.com/badge/dynamic/json?label=&query=star&url=https%3A%2F%2Fwww.itwmw.com%2Ftools%2Fgitee.php%3Fname%3Dwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Stars&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/stargazers) -[![fork](https://icon.itwmw.com/badge/dynamic/json?label=&query=fork&url=https%3A%2F%2Fwww.itwmw.com%2Ftools%2Fgitee.php%3Fname%3Dwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Forks&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/members) +[![Star](https://icon.itwmw.com/badge/dynamic/json?label=&query=star&url=https%3A%2F%2Fwww.itwmw.com%2Ftools%2Fgitee.php%3Fname%3Dwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Stars&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/stargazers) +[![Fork](https://icon.itwmw.com/badge/dynamic/json?label=&query=fork&url=https%3A%2F%2Fwww.itwmw.com%2Ftools%2Fgitee.php%3Fname%3Dwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Forks&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/members) ![Docs](https://icon.itwmw.com/badge/License-Apache--2.0-blue) ![Version Support](https://icon.itwmw.com/badge/PHP-%5E7.2.5%7C%5E8.0%7C%5E8.1-brightgreen?logo=php&logoColor=violet) [![Docs](https://icon.itwmw.com/badge/Docs-passing-brightgreen)](https://v.neww7.com) ![Tests](https://icon.itwmw.com/badge/Tests-100%25%20passed-brightgreen) -![document](https://icon.itwmw.com/packagist/dt/w7/engine-validate?style=social&logo=packagist) +![Download](https://icon.itwmw.com/packagist/dt/w7/engine-validate?style=social&logo=packagist) ## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 diff --git a/composer.json b/composer.json index 511966c..86d428f 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ }, "require-dev": { "laravel-lang/lang": "^8.0", - "phpunit/phpunit": "^8.5", + "phpunit/phpunit": "^9.5", "friendsofphp/php-cs-fixer": "^3.0" }, "autoload": { diff --git a/phpunit.xml b/phpunit.xml index bcebe84..12a341d 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,7 +1,30 @@ - + tests/Test + + + src + + + src/Providers + src/Exception + + + + + \ No newline at end of file diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 2dc008f..fe521de 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -143,11 +143,11 @@ class ValidateScene extends RuleManagerScene * Add a method that needs to be executed before validation * * @link https://v.neww7.com/en/3/Scene.html#before - * @param string $callbackName Validate the method name in the class - * @param mixed ...$params Parameters to be passed to the method + * @param string|Closure|callable $callbackName {@see Closure},{@see callable} or Validate the method name in the class + * @param mixed ...$params Parameters to be passed to the method * @return $this */ - public function before(string $callbackName, ...$params): ValidateScene + public function before($callbackName, ...$params): ValidateScene { $this->befores[] = [$callbackName, $params]; return $this; @@ -157,11 +157,11 @@ class ValidateScene extends RuleManagerScene * Add a method that needs to be executed after validation * * @link https://v.neww7.com/en/3/Scene.html#after - * @param string $callbackName Validate the method name in the class - * @param mixed ...$params Parameters to be passed to the method + * @param string|Closure|callable $callbackName {@see Closure},{@see callable} or Validate the method name in the class + * @param mixed ...$params Parameters to be passed to the method * @return $this */ - public function after(string $callbackName, ...$params): ValidateScene + public function after($callbackName, ...$params): ValidateScene { $this->afters[] = [$callbackName, $params]; return $this; diff --git a/src/Validate.php b/src/Validate.php index 4553b80..154273b 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -17,7 +17,6 @@ use Illuminate\Support\Str; use Illuminate\Validation\Factory; use Illuminate\Validation\ValidationData; use Illuminate\Validation\ValidationException; -use LogicException; use W7\Validate\Exception\ValidateException; use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\Concerns\DefaultInterface; @@ -345,7 +344,7 @@ class Validate extends RuleManager private function next(string $next, array $rules, string $currentSceneName = ''): array { if ($next === $currentSceneName) { - throw new LogicException('The scene used cannot be the same as the current scene.'); + throw new ValidateRuntimeException('The scene used cannot be the same as the current scene.'); } // Pre-validation @@ -385,8 +384,6 @@ class Validate extends RuleManager $callbacks = $this->afters; $typeName = 'after'; break; - default: - throw new LogicException('Type Error'); } if (empty($callbacks)) { @@ -395,11 +392,15 @@ class Validate extends RuleManager foreach ($callbacks as $callback) { list($callback, $param) = $callback; - $callback = $typeName . ucfirst($callback); - if (!method_exists($this, $callback)) { - throw new LogicException('Method Not Found'); + if (!is_callable($callback)) { + $callback = $typeName . ucfirst($callback); + if (!method_exists($this, $callback)) { + throw new ValidateRuntimeException('Method Not Found'); + } + $callback = [$this, $callback]; } - if (($result = call_user_func([$this, $callback], $data, ...$param)) !== true) { + + if (($result = call_user_func($callback, $data, ...$param)) !== true) { if (isset($this->message[$result])) { $result = $this->getMessageProvider()->handleMessage($this->message[$result]); } @@ -691,8 +692,6 @@ class Validate extends RuleManager case 2: $type = 'afters'; break; - default: - throw new LogicException('Type Error'); } if (is_string($callback)) { diff --git a/tests/Test/TestCustomMessageProvider.php b/tests/Test/TestCustomMessageProvider.php new file mode 100644 index 0000000..3622020 --- /dev/null +++ b/tests/Test/TestCustomMessageProvider.php @@ -0,0 +1,43 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Tests\Test; + +use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Exception\ValidateRuntimeException; +use W7\Validate\Support\Concerns\MessageProviderInterface; +use W7\Validate\Support\MessageProvider; +use W7\Validate\Validate; + +class TestMessageProvider extends MessageProvider implements MessageProviderInterface +{ +} + +class TestCustomMessageProvider extends BaseTestValidate +{ + /** + * @test 测试多种方式设置消息处理器 + * + * @throws \W7\Validate\Exception\ValidateException + */ + public function testSetMessageProvider() + { + Validate::make()->setMessageProvider(TestMessageProvider::class); + Validate::make()->setMessageProvider(new TestMessageProvider()); + Validate::make()->setMessageProvider(function () { + return new TestMessageProvider(); + }); + + $this->expectException(ValidateRuntimeException::class); + Validate::make()->setMessageProvider('Test'); + } +} diff --git a/tests/Test/TestCustomRuleAndMessage.php b/tests/Test/TestCustomRuleAndMessage.php index 27b47b5..3f8614d 100644 --- a/tests/Test/TestCustomRuleAndMessage.php +++ b/tests/Test/TestCustomRuleAndMessage.php @@ -12,9 +12,11 @@ namespace W7\Tests\Test; +use Illuminate\Contracts\Validation\ImplicitRule; use Illuminate\Support\Arr; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; +use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; @@ -100,8 +102,40 @@ class TestDependentRule extends Validate ]; } +class TestImplicitRuleClass extends BaseRule implements ImplicitRule +{ + protected $message = '给定的值为空'; + + public function passes($attribute, $value): bool + { + return !empty($value); + } +} + class TestCustomRuleAndMessage extends BaseTestValidate { + public function testCustomRuleIsObject() + { + $v = Validate::make([ + 'id' => [ + new class extends BaseRule { + protected $message = '输入的字符不合格'; + + public function passes($attribute, $value): bool + { + return is_numeric($value); + } + } + ] + ]); + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('输入的字符不合格'); + + $v->check([ + 'id' => 'aaa' + ]); + } /** * @test 测试依赖规则 * @@ -120,7 +154,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate } /** - * @test 测试当值为空,规则也依旧执行 + * @test 测试当值为空,规则也依旧执行(方法扩展) * @throws ValidateException */ public function testImplicitRule() @@ -130,6 +164,22 @@ class TestCustomRuleAndMessage extends BaseTestValidate TestImplicitRule::make()->check([]); } + /** + * @test 测试当值为空,规则也依旧执行(规则类) + * + * @throws ValidateException + */ + public function testImplicitRuleForRuleClass() + { + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('给定的值为空'); + Validate::make([ + 'a' => [ + new TestImplicitRuleClass() + ] + ])->check([]); + } + /** * @test 测试扩展规则和对应的错误消息是否生效 * @throws ValidateException diff --git a/tests/Test/TestDataFilter.php b/tests/Test/TestDataFilter.php index 150ab90..95b8c24 100644 --- a/tests/Test/TestDataFilter.php +++ b/tests/Test/TestDataFilter.php @@ -13,6 +13,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; +use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\DataAttribute; use W7\Validate\Support\ValidateScene; @@ -104,6 +105,11 @@ class TestDataFilter extends BaseTestValidate } } + /** + * @test 测试当数据不存在时,过滤器的处理 + * + * @throws \W7\Validate\Exception\ValidateException + */ public function testNotHasDataFilter() { $v = new class extends Validate { @@ -120,6 +126,11 @@ class TestDataFilter extends BaseTestValidate $this->assertArrayNotHasKey('id', $data); } + /** + * @test 测试场景中取消设置过滤器 + * + * @throws \W7\Validate\Exception\ValidateException + */ public function testCancelFilter() { $v = new class extends Validate { @@ -144,6 +155,11 @@ class TestDataFilter extends BaseTestValidate $this->assertSame('你好', $data['id']); } + /** + * @test 测试过滤器中删除字段 + * + * @throws \W7\Validate\Exception\ValidateException + */ public function testFilterDeleteField() { $v = new class extends Validate { @@ -168,4 +184,29 @@ class TestDataFilter extends BaseTestValidate $this->assertTrue(empty($data)); } + + /** + * @test 测试不存在的过滤器 + * + * @throws \W7\Validate\Exception\ValidateException + */ + public function testNonexistentFilter() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'required' + ]; + + protected function sceneTest(ValidateScene $scene) + { + $scene->only(['a'])->filter('a', 'test'); + } + }; + + $this->expectException(ValidateRuntimeException::class); + + $v->scene('test')->check([ + 'a' => 123 + ]); + } } diff --git a/tests/Test/TestHandlerEvent.php b/tests/Test/TestHandlerEvent.php index 58cf3db..914433d 100644 --- a/tests/Test/TestHandlerEvent.php +++ b/tests/Test/TestHandlerEvent.php @@ -17,6 +17,7 @@ use W7\Tests\Material\BaseTestValidate; use W7\Tests\Material\Count; use W7\Tests\Material\TestValidate; use W7\Validate\Exception\ValidateException; +use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\Event\ValidateEventAbstract; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; @@ -208,4 +209,65 @@ class TestHandlerEvent extends BaseTestValidate $this->assertEquals(1, Count::value('customSceneEventAfter')); $this->assertEquals(1, Count::value('customSceneEventBefore')); } + + /** + * @test 测试场景中 事件和闭包方法的优先级 + * + * @throws ValidateException + */ + public function testEventPriority() + { + $v = new class extends Validate { + protected function sceneEventCallback(ValidateScene $scene) + { + $scene->setEventPriority(false) + ->event(TestSceneEventA::class) + ->before(function () { + Count::assertEquals(0, 'sceneEventBefore-A'); + return true; + }) + ->after(function () { + Count::assertEquals(1, 'sceneEventAfter-A'); + return true; + }); + } + + protected function sceneEventPriority(ValidateScene $scene) + { + $scene->setEventPriority(true) + ->event(TestSceneEventA::class) + ->before(function () { + Count::assertEquals(1, 'sceneEventBefore-A'); + return true; + }) + ->after(function () { + Count::assertEquals(0, 'sceneEventAfter-A'); + return true; + }); + } + }; + + Count::reset('sceneEventAfter-A'); + Count::reset('sceneEventBefore-A'); + $v->scene('eventPriority')->check([]); + Count::reset('sceneEventAfter-A'); + Count::reset('sceneEventBefore-A'); + $v->scene('eventCallback')->check([]); + } + + /** + * @test 测试当指定的事件类不存在时 + * + * @throws ValidateException + */ + public function testNonexistentEvent() + { + $v = new class extends Validate { + protected $event = [ + 'test' + ]; + }; + $this->expectException(ValidateRuntimeException::class); + $v->check([]); + } } diff --git a/tests/Test/TestHandlerFunction.php b/tests/Test/TestHandlerFunction.php index 23cc807..b592b4c 100644 --- a/tests/Test/TestHandlerFunction.php +++ b/tests/Test/TestHandlerFunction.php @@ -14,6 +14,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; +use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Validate; class TestHandlerFunction extends BaseTestValidate @@ -66,4 +67,19 @@ class TestHandlerFunction extends BaseTestValidate $v->scene('testBefore')->check([]); } + + /** + * @test 测试当指定的方法不存在时 + * + * @throws ValidateException + */ + public function testNonexistentFunction() + { + $v = Validate::make()->setScene([ + 'test' => ['after' => '111', 'before' => '222'] + ]); + + $this->expectException(ValidateRuntimeException::class); + $v->scene('test')->check([]); + } } diff --git a/tests/Test/TestValidateMessage.php b/tests/Test/TestValidateMessage.php index 6e2dd97..6d20a26 100644 --- a/tests/Test/TestValidateMessage.php +++ b/tests/Test/TestValidateMessage.php @@ -13,10 +13,21 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; -use W7\Validate\RuleManager; +use W7\Validate\Exception\ValidateException; +use W7\Validate\Support\Event\ValidateEventAbstract; use W7\Validate\Support\MessageProvider; +use W7\Validate\Support\ValidateScene; +use W7\Validate\Validate; -class TestMessage extends RuleManager +class TestErrorMessageEvent extends ValidateEventAbstract +{ + public function afterValidate(): bool + { + $this->message = 'user.required'; + return false; + } +} +class TestMessage extends Validate { protected $rule = [ 'user' => 'required|email', @@ -42,6 +53,28 @@ class TestMessage extends RuleManager 'remark' => '备注', 'captcha' => '验证码', ]; + + protected function sceneTestSceneEventClosure(ValidateScene $scene) + { + $scene->after(function () { + return 'user.required'; + }); + } + + protected function sceneTestSceneEventCallable(ValidateScene $scene) + { + $scene->before('testMessage'); + } + + protected function sceneTestSceneEvent(ValidateScene $scene) + { + $scene->event(TestErrorMessageEvent::class); + } + + protected function beforeTestMessage(): string + { + return 'pass.required'; + } } class TestValidateMessage extends BaseTestValidate @@ -55,6 +88,9 @@ class TestValidateMessage extends BaseTestValidate $this->testMessage = new TestMessage(); } + /** + * @test 测试消息处理器对错误消息的处理是否符合预期 + */ public function testGetCustomMessage() { $message = (new MessageProvider())->setRuleManager($this->testMessage); @@ -67,4 +103,40 @@ class TestValidateMessage extends BaseTestValidate $this->assertEquals('你输入的密码与:attribute不一致', $message->getMessage('re_pass', 'eq')); } + + /** + * @test 测试在验证场景中的事件方法中(闭包方式)返回错误 + * + * @throws ValidateException + */ + public function testMessageInSceneEventClosure() + { + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('用户名必须填写'); + $this->testMessage->scene('testSceneEventClosure')->check([]); + } + + /** + * @test 测试在验证场景中的事件方法中(Callable方式)返回错误 + * + * @throws ValidateException + */ + public function testMessageInSceneEventCallable() + { + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('密码必须填写'); + $this->testMessage->scene('testSceneEventCallable')->check([]); + } + + /** + * @test 测试在验证场景中的事件返回错误 + * + * @throws ValidateException + */ + public function testMessageInSceneEvent() + { + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('用户名必须填写'); + $this->testMessage->scene('testSceneEvent')->check([]); + } } diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index 1023180..2c0832e 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -15,6 +15,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\ArticleValidate; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; +use W7\Validate\Validate; class TestValidateScene extends BaseTestValidate { @@ -86,4 +87,23 @@ class TestValidateScene extends BaseTestValidate ]); $this->assertEquals('1', $data['content']); } + + /** + * @test 测试当指定的验证场景不存在时,是否验证全部的规则 + */ + public function testNotFountSceneName() + { + $v = new class extends Validate { + protected $rule = [ + 'user' => 'required', + 'pass' => 'required' + ]; + }; + + try { + $v->scene('notFount')->check([]); + } catch (ValidateException $e) { + $this->assertCount(2, $e->getData()); + } + } } diff --git a/tests/Test/TestValidateSceneNext.php b/tests/Test/TestValidateSceneNext.php index b552413..58b0087 100644 --- a/tests/Test/TestValidateSceneNext.php +++ b/tests/Test/TestValidateSceneNext.php @@ -15,6 +15,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; use W7\Tests\Material\Count; use W7\Validate\Exception\ValidateException; +use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Validate; class TestValidateSceneNext extends BaseTestValidate @@ -111,4 +112,51 @@ class TestValidateSceneNext extends BaseTestValidate $this->assertEquals(1, $data['a']); Count::assertEquals(1, 'ruleTest'); } + + /** + * @test 测试在场景中,当next指定的场景和当前的场景名一致时,是否会导致死循环 + * + * @throws ValidateException + */ + public function testNextSceneNameEqCurrentSceneName() + { + $v = new class extends Validate { + protected $scene = [ + 'test' => ['next' => 'test'] + ]; + }; + + $this->expectException(ValidateRuntimeException::class); + $this->expectExceptionMessage('The scene used cannot be the same as the current scene.'); + $v->scene('test')->check([]); + } + + /** + * @test 测试场景选择器中直接返回字段数组 + * + * @throws ValidateException + */ + public function testSceneSelectorFields() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'required' + ]; + + protected $scene = [ + 'test' => ['next' => 'getFields'] + ]; + + protected function getFieldsSelector(array $data): array + { + return ['a']; + } + }; + + $data = $v->scene('test')->check([ + 'a' => 123 + ]); + + $this->assertSame(123, $data['a']); + } } -- Gitee From 114b1ea46dff83b6b63207791ee096c250899b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 9 Sep 2021 19:06:19 +0800 Subject: [PATCH 124/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0SomeTimes?= =?UTF-8?q?=E8=A7=84=E5=88=99=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Test/TestValidateScene.php | 60 ++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index 2c0832e..6c8e3f6 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -15,8 +15,34 @@ namespace W7\Tests\Test; use W7\Tests\Material\ArticleValidate; use W7\Tests\Material\BaseTestValidate; use W7\Validate\Exception\ValidateException; +use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; +class TestSomeTimes extends Validate +{ + protected $message = [ + 'a.required' => 'a不能为空', + 'b.required' => 'b不能为空', + ]; + protected function sceneTest(ValidateScene $scene) + { + $scene->appendCheckField('a') + ->appendCheckField('aIsRequired') + ->append('aIsRequired', 'required') + ->sometimes('a', 'required', function ($data) { + return 1 == $data['aIsRequired']; + }); + } + + protected function sceneTestSomeTimesMultiField(ValidateScene $scene) + { + $scene->appendCheckField('b') + ->appendCheckField('a') + ->sometimes(['a', 'b'], 'required', function () { + return true; + }); + } +} class TestValidateScene extends BaseTestValidate { protected $userInput; @@ -106,4 +132,38 @@ class TestValidateScene extends BaseTestValidate $this->assertCount(2, $e->getData()); } } + + /** + * @test 测试sometimes规则 + * + * @throws ValidateException + */ + public function testSometimesRule() + { + $v = TestSomeTimes::make(); + $data = $v->scene('test')->check([ + 'aIsRequired' => 0 + ]); + + $this->assertSame(0, $data['aIsRequired']); + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('a不能为空'); + $v->scene('test')->check([ + 'aIsRequired' => 1 + ]); + } + + /** + * @test 测试sometimes为多个字段附加规则 + */ + public function testSometimesMultiField() + { + $v = TestSomeTimes::make(); + try { + $v->scene('testSomeTimesMultiField')->check([]); + } catch (ValidateException $e) { + $this->assertCount(2, $e->getData()); + } + } } -- Gitee From b7c61cad4365adc79196d0e664cd0cc8d893bc07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 10 Sep 2021 20:27:27 +0800 Subject: [PATCH 125/152] =?UTF-8?q?[A]=20=E5=9C=BA=E6=99=AF=E4=B8=ADappend?= =?UTF-8?q?=E8=A7=84=E5=88=99=E6=94=AF=E6=8C=81=E9=97=AD=E5=8C=85=E8=A7=84?= =?UTF-8?q?=E5=88=99=20[A]=20=E8=87=AA=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99?= =?UTF-8?q?=E7=B1=BB=E6=94=AF=E6=8C=81=E7=8B=AC=E7=AB=8B=E8=B0=83=E7=94=A8?= =?UTF-8?q?=20[D]=20=E5=88=A0=E9=99=A4=E8=87=AA=E5=AE=9A=E4=B9=89=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E4=B8=AD=E7=9A=84setData=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/Concerns/SceneInterface.php | 16 ++++++++++-- src/Support/Rule/BaseRule.php | 10 ++++++++ src/Support/RuleManagerScene.php | 6 +++-- src/Support/ValidateScene.php | 12 --------- tests/Test/TestCustomRuleAndMessage.php | 11 +++++++- tests/Test/TestValidateScene.php | 34 +++++++++++++++++++++++++ 6 files changed, 72 insertions(+), 17 deletions(-) diff --git a/src/Support/Concerns/SceneInterface.php b/src/Support/Concerns/SceneInterface.php index b4d649e..13a219a 100644 --- a/src/Support/Concerns/SceneInterface.php +++ b/src/Support/Concerns/SceneInterface.php @@ -12,6 +12,8 @@ namespace W7\Validate\Support\Concerns; +use Closure; + interface SceneInterface { /** @@ -27,8 +29,18 @@ interface SceneInterface * Adding a validation rule for a field * * @link https://v.neww7.com/en/3/Scene.html#append - * @param string $field - * @param string|array $rules + * @param string $field + * @param string|array|Closure $rules If you only need the functionality of a custom rule once throughout your application, + * you may use a closure instead of a rule object. + * The closure receives the attribute's name, + * the attribute's value, and a `$fail` callback that should be called if validation fails: + * + * function ($attribute, $value, $fail) { + * if ($value === 'foo') { + * $fail('The '.$attribute.' is invalid.'); + * } + * }, + * * @return $this */ public function append(string $field, $rules): SceneInterface; diff --git a/src/Support/Rule/BaseRule.php b/src/Support/Rule/BaseRule.php index bfcd49b..499e1ff 100644 --- a/src/Support/Rule/BaseRule.php +++ b/src/Support/Rule/BaseRule.php @@ -46,4 +46,14 @@ abstract class BaseRule implements RuleInterface { return $this->getMessage(); } + + public static function make(...$params): BaseRule + { + return new static(...$params); + } + + public function check($data): bool + { + return $this->passes('', $data); + } } diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php index e02b9cb..2b1e7fa 100644 --- a/src/Support/RuleManagerScene.php +++ b/src/Support/RuleManagerScene.php @@ -59,10 +59,12 @@ class RuleManagerScene implements SceneInterface $this->checkRules[$field] = explode('|', $this->checkRules[$field]); } - if (!is_array($rules)) { + if (is_string($rules)) { $rules = explode('|', $rules); + array_push($this->checkRules[$field], ...$rules); + } else { + array_push($this->checkRules[$field], $rules); } - array_push($this->checkRules[$field], ...$rules); } return $this; diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index fe521de..cf08614 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -253,18 +253,6 @@ class ValidateScene extends RuleManagerScene return $this; } - /** - * Provide the data to be validated - * - * @param array $data - * @return $this - */ - public function setData(array $data = []): ValidateScene - { - $this->checkData = $data; - return $this; - } - /** * Get the current validation data * diff --git a/tests/Test/TestCustomRuleAndMessage.php b/tests/Test/TestCustomRuleAndMessage.php index 3f8614d..f979446 100644 --- a/tests/Test/TestCustomRuleAndMessage.php +++ b/tests/Test/TestCustomRuleAndMessage.php @@ -15,6 +15,7 @@ namespace W7\Tests\Test; use Illuminate\Contracts\Validation\ImplicitRule; use Illuminate\Support\Arr; use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\Rules\Length; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\ValidateScene; @@ -47,7 +48,6 @@ class TestCustomRuleB extends TestCustomRuleA return '十' === (string)$value; } } - class TestExtendRule extends Validate { public function __construct() @@ -230,4 +230,13 @@ class TestCustomRuleAndMessage extends BaseTestValidate $this->assertFalse(isset($data), '验证错误的通过'); } + + /** + * @ test 规则单独使用 + */ + public function testSeparateUseRules() + { + $this->assertTrue(Length::make(5)->check(12345)); + $this->assertFalse(Length::make(5)->check(1234)); + } } diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index 6c8e3f6..74c2986 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -14,6 +14,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\ArticleValidate; use W7\Tests\Material\BaseTestValidate; +use W7\Tests\Material\Count; use W7\Validate\Exception\ValidateException; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; @@ -166,4 +167,37 @@ class TestValidateScene extends BaseTestValidate $this->assertCount(2, $e->getData()); } } + + /** + * @test 测试在场景中增加闭包规则 + * @throws ValidateException + */ + public function testAppendClosureRule() + { + $v = new class extends Validate { + protected function sceneTest(ValidateScene $scene) + { + $scene->appendCheckField('a') + ->append('a', function ($attribute, $value, $fail) { + Count::incremental('testAppendClosureRule'); + if (!is_numeric($value)) { + $fail('a必须为数字'); + } + }); + } + }; + + $data = $v->scene('test')->check([ + 'a' => 123 + ]); + + $this->assertSame(123, $data['a']); + Count::assertEquals(1, 'testAppendClosureRule'); + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('a必须为数字'); + $v->scene('test')->check([ + 'a' => 'aaa' + ]); + } } -- Gitee From bcc63e0b95f84050d8e9966e851b91b39b0966e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 11 Sep 2021 10:45:06 +0800 Subject: [PATCH 126/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=83=A8?= =?UTF-8?q?=E5=88=86=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=20[U]=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=BC=80=E5=8F=91=E4=BE=9D=E8=B5=96=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 4 ++-- tests/Material/Event/CheckIsChs.php | 32 ++++++++++++++++++----------- tests/Test/TestHandlerEvent.php | 27 ++++++++++++++++++++++++ tests/Test/TestRuleManagerScene.php | 28 +++++++++++++++++++++++-- 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index 86d428f..813ad64 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,8 @@ "illuminate/validation": "^6.0|^7.0|^8.0" }, "require-dev": { - "laravel-lang/lang": "^8.0", - "phpunit/phpunit": "^9.5", + "laravel-lang/lang": "*", + "phpunit/phpunit": "^8|^9", "friendsofphp/php-cs-fixer": "^3.0" }, "autoload": { diff --git a/tests/Material/Event/CheckIsChs.php b/tests/Material/Event/CheckIsChs.php index cf77436..d712fca 100644 --- a/tests/Material/Event/CheckIsChs.php +++ b/tests/Material/Event/CheckIsChs.php @@ -1,24 +1,32 @@ + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ namespace W7\Tests\Material\Event; - use W7\Validate\Support\Event\ValidateEventAbstract; class CheckIsChs extends ValidateEventAbstract { - protected $field; + protected $field; - public $message = "不是中文"; + public $message = '不是中文'; - public function __construct($field) - { - $this->field = $field; - } + public function __construct($field) + { + $this->field = $field; + } - public function afterValidate(): bool - { - return is_scalar($this->data[$this->field]) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$this->data[$this->field]); - } -} \ No newline at end of file + public function afterValidate(): bool + { + return is_scalar($this->data[$this->field]) && 1 === preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', (string)$this->data[$this->field]); + } +} diff --git a/tests/Test/TestHandlerEvent.php b/tests/Test/TestHandlerEvent.php index 914433d..c03d5a7 100644 --- a/tests/Test/TestHandlerEvent.php +++ b/tests/Test/TestHandlerEvent.php @@ -108,6 +108,17 @@ class TestCustomSceneEvent extends ValidateEventAbstract return true; } } + +class TestErrorEventForBefore extends ValidateEventAbstract +{ + public $message = '该操作已完成'; + + public function beforeValidate(): bool + { + Count::incremental('testEventBefore'); + return 1 === Count::value('testEventBefore'); + } +} class TestHandlerEvent extends BaseTestValidate { public function testErrorEvent() @@ -120,6 +131,22 @@ class TestHandlerEvent extends BaseTestValidate ]); } + public function testErrorEventForBefore() + { + $v = new class extends Validate { + protected $event = [ + TestErrorEventForBefore::class + ]; + }; + + $v->check([]); + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('该操作已完成'); + + $v->check([]); + } + public function testEventIsCheckName() { $v = new TestValidate(); diff --git a/tests/Test/TestRuleManagerScene.php b/tests/Test/TestRuleManagerScene.php index fde857d..abbef85 100644 --- a/tests/Test/TestRuleManagerScene.php +++ b/tests/Test/TestRuleManagerScene.php @@ -32,7 +32,7 @@ class TestRuleManagerScene extends BaseTestValidate 'pass' => 'required|lengthBetween:6,16' ]; - $this->assertEquals($needRules, $userRule->scene('login')->getRules(null,true)); + $this->assertEquals($needRules, $userRule->scene('login')->getRules(null, true)); $this->assertEquals($needRules, $userRule->getRules(null, 'login')); $this->assertEquals($needRules, $userRule->getInitialRules('login')); } @@ -40,7 +40,7 @@ class TestRuleManagerScene extends BaseTestValidate public function testCustomValidateScene() { $userRule = new UserRulesManager(); - $rules = $userRule->scene('register')->getRules(null,true); + $rules = $userRule->scene('register')->getRules(null, true); $this->assertCount(4, $rules); $this->assertArrayHasKey('remark', $rules); @@ -83,4 +83,28 @@ class TestRuleManagerScene extends BaseTestValidate $this->assertEquals('验证码错误', $messages['captcha.' . $extendRuleName]); } + + /** + * @test 测试当规则管理器使用了不存在的场景名,结果是否取出全部规则 + */ + public function testGetRulesUsingNonExistentSceneName() + { + $v = new class extends UserRulesManager { + protected $rule = [ + 'user' => 'required', + 'pass' => 'required', + 'code' => 'required', + 'name' => 'required' + ]; + + protected $scene = [ + 'login' => ['user', 'pass'] + ]; + }; + + $rules = $v->scene('login')->getRules(); + $this->assertSame(2, \count(array_intersect(array_keys($rules), ['user', 'pass']))); + $rules = $v->scene('nonExistentSceneName')->getRules(); + $this->assertSame(4, \count(array_intersect(array_keys($rules), ['user', 'pass', 'code', 'name']))); + } } -- Gitee From fd989d7f91293ec478feae8b22fa3a2635285f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sun, 12 Sep 2021 11:15:36 +0800 Subject: [PATCH 127/152] =?UTF-8?q?[U]=20=E4=BC=98=E5=8C=96=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E8=87=AA=E5=AE=9A=E4=B9=89=E8=A7=84=E5=88=99=20[F]=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=AA=8C=E8=AF=81=E5=AE=8C=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E4=B8=8D=E4=BC=9A=E8=87=AA=E5=8A=A8=E9=87=8D=E7=BD=AE=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20[A]=20=E6=B7=BB=E5=8A=A0=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/RuleManager.php | 18 ++-- src/Support/Storage/ValidateCollection.php | 5 - src/Validate.php | 3 +- tests/Test/TestCustomRuleAndMessage.php | 30 ++++++ tests/Test/TestDataDefault.php | 5 +- tests/Test/TestRuleManagerGet.php | 117 +++++++++++++++++++++ tests/Test/TestValidateScene.php | 37 +++++++ 8 files changed, 198 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index deabd30..5db0e23 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![Docs](https://icon.itwmw.com/badge/License-Apache--2.0-blue) ![Version Support](https://icon.itwmw.com/badge/PHP-%5E7.2.5%7C%5E8.0%7C%5E8.1-brightgreen?logo=php&logoColor=violet) [![Docs](https://icon.itwmw.com/badge/Docs-passing-brightgreen)](https://v.neww7.com) -![Tests](https://icon.itwmw.com/badge/Tests-100%25%20passed-brightgreen) +![Tests](https://icon.itwmw.com/badge/Test%20Coverage-94.90%25-brightgreen) ![Download](https://icon.itwmw.com/packagist/dt/w7/engine-validate?style=social&logo=packagist) ## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 diff --git a/src/RuleManager.php b/src/RuleManager.php index dc95a62..3b82587 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -199,14 +199,14 @@ class RuleManager list($ruleName, $param) = Common::getKeyAndParam($ruleName, true); + if (isset($rulesClass[$ruleName]) && 0 === $rulesClass[$ruleName]) { + return false; + } + foreach (ValidateConfig::instance()->getRulePath() as $rulesPath) { $ruleNameSpace = $rulesPath . ucfirst($ruleName); if (isset($rulesClass[$ruleNameSpace])) { - if (0 === $rulesClass[$ruleNameSpace]) { - continue; - } else { - return new $ruleNameSpace(...$param); - } + return new $ruleNameSpace(...$param); } elseif (class_exists($ruleNameSpace) && is_subclass_of($ruleNameSpace, BaseRule::class)) { $rulesClass[$ruleNameSpace] = 1; return new $ruleNameSpace(...$param); @@ -495,7 +495,7 @@ class RuleManager * *

    If you have defined an extension rule using the {@see RuleManager}, * you need to call the `getCheckRules` method first before calling this method. - * Otherwise the error message may not match the extension rule name.

    + * Otherwise, the error message may not match the extension rule name.

    * * @param string $key Full message key * @param string|null $rule If the first value is a field name, the second value is a rule, otherwise leave it blank @@ -504,12 +504,10 @@ class RuleManager protected function getMessage(string $key, ?string $rule = null) { if (null !== $rule) { - $messageName = Common::makeMessageName($key, $rule); - } else { - $messageName = $key; + $key = Common::makeMessageName($key, $rule); } - return $this->message[$messageName] ?? ''; + return $this->message[$key] ?? ''; } /** diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index 0687be4..dee6de5 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -156,9 +156,4 @@ class ValidateCollection extends Collection { $this->offsetSet($key, $value); } - - public function __toArray(): array - { - return $this->toArray(); - } } diff --git a/src/Validate.php b/src/Validate.php index 154273b..3925163 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -257,6 +257,7 @@ class Validate extends RuleManager $data = $this->handlerFilter($data, $fields); $this->initScene(); + $this->scene(null); return $data; } @@ -359,7 +360,7 @@ class Validate extends RuleManager } } - if (empty($next) || false === $next) { + if (empty($next)) { return []; } diff --git a/tests/Test/TestCustomRuleAndMessage.php b/tests/Test/TestCustomRuleAndMessage.php index f979446..ab98414 100644 --- a/tests/Test/TestCustomRuleAndMessage.php +++ b/tests/Test/TestCustomRuleAndMessage.php @@ -20,6 +20,7 @@ use W7\Validate\Exception\ValidateException; use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; +use function PHPUnit\Framework\assertEquals; class TestCustomRuleA extends Validate { @@ -239,4 +240,33 @@ class TestCustomRuleAndMessage extends BaseTestValidate $this->assertTrue(Length::make(5)->check(12345)); $this->assertFalse(Length::make(5)->check(1234)); } + + /** + * @test 测试传递参数到自定义规则 + * @throws ValidateException + */ + public function testPassingParamsToCustomRules() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'test:111' + ]; + + protected function ruleTest($attribute, $value, $parameters) + { + assertEquals(111, $parameters[0]); + return false; + } + + protected $message = [ + 'a.test' => 'testErrorMessage' + ]; + }; + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('testErrorMessage'); + $v->check([ + 'a' => 123 + ]); + } } diff --git a/tests/Test/TestDataDefault.php b/tests/Test/TestDataDefault.php index 75d147a..2e6aa59 100644 --- a/tests/Test/TestDataDefault.php +++ b/tests/Test/TestDataDefault.php @@ -153,11 +153,12 @@ class TestDataDefault extends BaseTestValidate ->default('name', '小张'); } }; - $this->expectException(ValidateException::class); - $v->check([]); $data = $v->scene('test')->check([]); $this->assertSame('小张', $data['name']); + + $this->expectException(ValidateException::class); + $v->check([]); } public function testCancelDefaultValue() diff --git a/tests/Test/TestRuleManagerGet.php b/tests/Test/TestRuleManagerGet.php index cd4a841..42dbb96 100644 --- a/tests/Test/TestRuleManagerGet.php +++ b/tests/Test/TestRuleManagerGet.php @@ -14,6 +14,7 @@ namespace W7\Tests\Test; use W7\Tests\Material\BaseTestValidate; use W7\Tests\Material\UserRulesManager; +use W7\Validate\RuleManager; class TestRuleManagerGet extends BaseTestValidate { @@ -58,4 +59,120 @@ class TestRuleManagerGet extends BaseTestValidate $this->assertCount(2, $userRules->scene('login')->getRules()); $this->assertCount(2, $userRules::login()[0]); } + + /** + * @test 测试清空规则管理器的场景 + */ + public function testClearScene() + { + $v = new class extends RuleManager { + protected $rule = [ + 'user' => 'required', + 'pass' => 'required', + 'name' => 'required' + ]; + + protected $scene = [ + 'login' => ['user', 'pass'] + ]; + }; + + $rules = $v->setScene()->scene('login')->getRules(); + $this->assertSame(3, \count(array_intersect(array_keys($rules), ['user', 'pass', 'name']))); + } + + /** + * @test 测试清空规则管理器的规则 + */ + public function testClearRules() + { + $v = new class extends RuleManager { + protected $rule = [ + 'user' => 'required', + 'pass' => 'required', + 'name' => 'required' + ]; + }; + + $rules = $v->setRules()->getRules(); + $this->assertEmpty($rules); + } + + /** + * @test 测试Message方法 + */ + public function testMessageMethod() + { + $v = new class extends RuleManager { + protected $rule = [ + 'user' => 'required|number', + 'pass' => 'required', + ]; + + protected $message = [ + 'code.required' => 'code不可为空', + ]; + }; + + $message = $v->setMessages() + ->setMessages([ + 'pass.required' => 'pass不可为空', + 'user.number' => '账号必须为纯数字' + ]) + ->setMessages([ + 'user.required' => '账号不可为空', + 'pass.required' => '密码不可为空' + ])->getMessages(); + + $this->assertEquals([ + 'user.required' => '账号不可为空', + 'pass.required' => '密码不可为空', + 'user.number' => '账号必须为纯数字' + ], $message); + + $this->assertEquals('账号不可为空', $v->getMessages('user.required')); + $this->assertEquals('账号不可为空', $v->getMessages('user', 'required')); + $this->assertEquals([ + 'user.required' => '账号不可为空', + 'pass.required' => '密码不可为空', + ], $v->getMessages(['user.required', 'pass.required'])); + + $this->assertEquals([ + 'user.required' => '账号不可为空', + 'user.number' => '账号必须为纯数字', + ], $v->getMessages('user', null, true)); + } + + /** + * @test 测试CustomAttributes方法 + */ + public function testCustomAttributesMethod() + { + $v = new class extends RuleManager { + protected $customAttributes = [ + 'user' => '账号' + ]; + }; + + $v->setCustomAttributes(); + + $this->assertEmpty($v->getCurrentSceneName()); + + $v->setCustomAttributes([ + 'user' => '账号' + ])->setCustomAttributes([ + 'user' => '用户名', + 'pass' => '密码' + ]); + + $this->assertEquals([ + 'user' => '用户名', + 'pass' => '密码' + ], $v->getCustomAttributes()); + + $this->assertEquals([ + 'user' => '用户名', + 'pass' => '密码' + ], $v->getCustomAttributes(['user', 'pass'])); + } } diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index 74c2986..09fb9c9 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -16,8 +16,10 @@ use W7\Tests\Material\ArticleValidate; use W7\Tests\Material\BaseTestValidate; use W7\Tests\Material\Count; use W7\Validate\Exception\ValidateException; +use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\ValidateScene; use W7\Validate\Validate; +use function PHPUnit\Framework\assertEquals; class TestSomeTimes extends Validate { @@ -200,4 +202,39 @@ class TestValidateScene extends BaseTestValidate 'a' => 'aaa' ]); } + + /** + * @test 测试在场景中获取验证的值 + * @throws ValidateException + */ + public function testGetDataForScene() + { + $v = new class extends Validate { + protected $rule = [ + 'name' => 'required' + ]; + + protected function sceneGetData(ValidateScene $scene) + { + $scene->only(['name']); + + assertEquals('名字', $scene->getData('name')); + } + + protected function sceneGetNonExistentData(ValidateScene $scene) + { + $scene->only(['name']); + $test = $scene->test; + } + }; + + $v->scene('getData')->check([ + 'name' => '名字' + ]); + + $this->expectException(ValidateRuntimeException::class); + $v->scene('getNonExistentData')->check([ + 'name' => '名字' + ]); + } } -- Gitee From 7b3981f35a2926719952ac58943952de8e0e53a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 13 Sep 2021 11:13:57 +0800 Subject: [PATCH 128/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E5=9C=A8?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E5=99=A8=E4=B8=8B=E6=97=A0=E6=B3=95=E4=BD=BF?= =?UTF-8?q?=E7=94=A8getRules=E6=96=B9=E6=B3=95=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- phpunit.xml | 1 + src/RuleManager.php | 11 +++- src/Support/MessageProvider.php | 6 +-- src/Support/RuleManagerScene.php | 4 +- src/Support/Storage/ValidateCollection.php | 30 +++++------ src/Validate.php | 7 ++- tests/Test/TestCustomMessageProvider.php | 20 ++++++++ tests/Test/TestValidateCollection.php | 16 ++++++ tests/Test/TestValidateScene.php | 60 ++++++++++++++++++++++ 10 files changed, 131 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 5db0e23..a2d2875 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![Docs](https://icon.itwmw.com/badge/License-Apache--2.0-blue) ![Version Support](https://icon.itwmw.com/badge/PHP-%5E7.2.5%7C%5E8.0%7C%5E8.1-brightgreen?logo=php&logoColor=violet) [![Docs](https://icon.itwmw.com/badge/Docs-passing-brightgreen)](https://v.neww7.com) -![Tests](https://icon.itwmw.com/badge/Test%20Coverage-94.90%25-brightgreen) +![Tests](https://icon.itwmw.com/badge/Test%20Coverage-100%25-brightgreen) ![Download](https://icon.itwmw.com/packagist/dt/w7/engine-validate?style=social&logo=packagist) ## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 diff --git a/phpunit.xml b/phpunit.xml index 12a341d..dc2d580 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,6 +22,7 @@ src/Providers src/Exception + src/Support/Storage/ValidateConfig.php diff --git a/src/RuleManager.php b/src/RuleManager.php index 3b82587..55655a9 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -58,6 +58,7 @@ class RuleManager /** * Regular validation rules * + * @link https://v.neww7.com/en/3/Validate.html#regex * @var array */ protected $regex = []; @@ -85,10 +86,18 @@ class RuleManager /** * Implicit extension method name + * * @var array */ private static $implicitRules = []; + /** + * Scene Management Class + * + * @var string + */ + protected $sceneProvider = RuleManagerScene::class; + /** * Set current validate scene * @@ -128,7 +137,7 @@ class RuleManager } if (method_exists($this, 'scene' . ucfirst($sceneName))) { - $scene = new RuleManagerScene($this->rule); + $scene = new $this->sceneProvider($this->rule); call_user_func([$this, 'scene' . ucfirst($sceneName)], $scene); return $scene->getRules(); } diff --git a/src/Support/MessageProvider.php b/src/Support/MessageProvider.php index 7e45c1a..9f3716f 100644 --- a/src/Support/MessageProvider.php +++ b/src/Support/MessageProvider.php @@ -72,12 +72,10 @@ class MessageProvider implements MessageProviderInterface public function getInitialMessage(string $key, ?string $rule = null): ?string { if (null !== $rule) { - $messageName = Common::makeMessageName($key, $rule); - } else { - $messageName = $key; + $key = Common::makeMessageName($key, $rule); } - return $this->message[$messageName] ?? ''; + return $this->message[$key] ?? ''; } /** @inheritDoc */ diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php index 2b1e7fa..690f920 100644 --- a/src/Support/RuleManagerScene.php +++ b/src/Support/RuleManagerScene.php @@ -98,8 +98,8 @@ class RuleManagerScene implements SceneInterface $rules = explode('|', $rules); } - if (false !== strpos($rule, ':')) { - $rule = substr($rule, 0, strpos($rule, ':')); + if (false !== ($index = strpos($rule, ':'))) { + $rule = substr($rule, 0, $index); } $rules = array_filter($rules, function ($value) use ($rule) { diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php index dee6de5..88e7fa4 100644 --- a/src/Support/Storage/ValidateCollection.php +++ b/src/Support/Storage/ValidateCollection.php @@ -84,7 +84,7 @@ class ValidateCollection extends Collection */ public function get($key, $default = null) { - if (false !== strpos($key, '*')) { + if (Str::contains($key, '*')) { $explicitPath = rtrim(explode('*', $key)[0], '.') ?: null; $results = []; $_default = rand(1e+5, 1e+10) . time(); @@ -94,29 +94,25 @@ class ValidateCollection extends Collection Arr::set($results, $explicitPath, $_value); } - if (! Str::contains($key, '*') || Str::endsWith($key, '*')) { - $value = Arr::get($this->items, $key); - } else { - data_set($results, $key, null, true); + data_set($results, $key, null, true); - $results = Arr::dot($results); + $results = Arr::dot($results); - $keys = []; + $keys = []; - $pattern = str_replace('\*', '[^\.]+', preg_quote($key)); + $pattern = str_replace('\*', '[^\.]+', preg_quote($key)); - foreach ($results as $_key => $_value) { - if (preg_match('/^' . $pattern . '/', $_key, $matches)) { - $keys[] = $matches[0]; - } + foreach ($results as $_key => $_value) { + if (preg_match('/^' . $pattern . '/', $_key, $matches)) { + $keys[] = $matches[0]; } + } - $value = []; - $keys = array_unique($keys); + $value = []; + $keys = array_unique($keys); - foreach ($keys as $key) { - $value[] = Arr::get($this->items, $key); - } + foreach ($keys as $key) { + $value[] = Arr::get($this->items, $key); } $value = $value ?: value($default); diff --git a/src/Validate.php b/src/Validate.php index 3925163..f05137c 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -141,6 +141,11 @@ class Validate extends RuleManager */ private $validateFields = []; + /** + * {@inheritdoc } + */ + protected $sceneProvider = ValidateScene::class; + /** * Create a validator * @@ -279,7 +284,7 @@ class Validate extends RuleManager } if (method_exists($this, 'scene' . ucfirst($sceneName))) { - $scene = new ValidateScene($this->rule, $this->checkData); + $scene = new $this->sceneProvider($this->rule, $this->checkData); call_user_func([$this, 'scene' . ucfirst($sceneName)], $scene); $this->events = $scene->events; $this->afters = $scene->afters; diff --git a/tests/Test/TestCustomMessageProvider.php b/tests/Test/TestCustomMessageProvider.php index 3622020..cd83fa9 100644 --- a/tests/Test/TestCustomMessageProvider.php +++ b/tests/Test/TestCustomMessageProvider.php @@ -40,4 +40,24 @@ class TestCustomMessageProvider extends BaseTestValidate $this->expectException(ValidateRuntimeException::class); Validate::make()->setMessageProvider('Test'); } + + public function testGetMessage() + { + $messageProvider = new TestMessageProvider(); + $messageProvider->setData([ + 'user' => 'admin', + 'pass' => '123456' + ]); + + $messageProvider->setCustomAttributes([ + 'user' => '账号', + 'pass' => '密码' + ]); + + $message = $messageProvider->handleMessage('@{user}:{:user},@{pass}:{:pass}'); + $this->assertEquals('账号:admin,密码:123456', $message); + + $message = $messageProvider->handleMessage(['@{user}:{:user},@{pass}:{:pass}']); + $this->assertEquals(['账号:admin,密码:123456'], $message); + } } diff --git a/tests/Test/TestValidateCollection.php b/tests/Test/TestValidateCollection.php index 40c3933..905506b 100644 --- a/tests/Test/TestValidateCollection.php +++ b/tests/Test/TestValidateCollection.php @@ -150,4 +150,20 @@ class TestValidateCollection extends BaseTestValidate $this->assertFalse($data->get('have')); } + + public function testGetArray() + { + $data = validate_collect([ + 'user' => 'test', + 'pass' => 123456 + ]); + + $this->assertSame('test', $data->user); + + $data->pass = 'root'; + $this->assertSame('root', $data->pass); + + $this->expectException(\Exception::class); + $this->assertSame('test', $data->nonExistent); + } } diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index 09fb9c9..9efaae7 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -237,4 +237,64 @@ class TestValidateScene extends BaseTestValidate 'name' => '名字' ]); } + + /** + * @test 测试在场景中动态移除验证规则 + */ + public function testRemoveRuleForScene() + { + $v = new class extends Validate { + protected $rule = [ + 'id' => 'required|max:100|min:1' + ]; + + protected function sceneRemoveRule(ValidateScene $scene) + { + $scene->only(['id']) + ->remove('id', 'required'); + } + + protected function sceneRemoveRuleForArray(ValidateScene $scene) + { + $scene->only(['id']) + ->remove('id', ['max', 'min']); + } + + protected function sceneRemoveRuleForHasParams(ValidateScene $scene) + { + $scene->only(['id']) + ->remove('id', 'max:100'); + } + }; + + $rules = $v->scene('removeRule')->getRules(); + $this->assertEquals(['max:100', 'min:1'], array_values($rules['id'])); + + $rules = $v->scene('removeRuleForArray')->getRules(); + $this->assertEquals(['required'], array_values($rules['id'])); + + $rules = $v->scene('removeRuleForHasParams')->getRules(); + $this->assertEquals(['required', 'min:1'], array_values($rules['id'])); + } + + public function testRemoveCheckField() + { + $v = new class extends Validate { + protected $rule = [ + 'user' => 'required', + 'pass' => 'required' + ]; + + protected function sceneTest(ValidateScene $scene) + { + $scene->only(['user', 'pass']) + ->removeCheckField('pass'); + } + }; + $rules = $v->getRules(); + $this->assertEquals(['user', 'pass'], array_keys($rules)); + + $rules = $v->scene('test')->getRules(); + $this->assertEquals(['user'], array_keys($rules)); + } } -- Gitee From 6ebe008704e975c3567d7f6ab2508695f4c88a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 14 Sep 2021 19:09:35 +0800 Subject: [PATCH 129/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AF=B4=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a2d2875..9a44027 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,16 @@ -# 增强表单验证 -[![Star](https://icon.itwmw.com/badge/dynamic/json?label=&query=star&url=https%3A%2F%2Fwww.itwmw.com%2Ftools%2Fgitee.php%3Fname%3Dwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Stars&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/stargazers) -[![Fork](https://icon.itwmw.com/badge/dynamic/json?label=&query=fork&url=https%3A%2F%2Fwww.itwmw.com%2Ftools%2Fgitee.php%3Fname%3Dwe7coreteam%2Fw7-engine-validate&logo=gitee&logoColor=fff&labelColor=c72e34&suffix=%20Forks&color=383d48)](https://gitee.com/we7coreteam/w7-engine-validate/members) -![Docs](https://icon.itwmw.com/badge/License-Apache--2.0-blue) -![Version Support](https://icon.itwmw.com/badge/PHP-%5E7.2.5%7C%5E8.0%7C%5E8.1-brightgreen?logo=php&logoColor=violet) -[![Docs](https://icon.itwmw.com/badge/Docs-passing-brightgreen)](https://v.neww7.com) -![Tests](https://icon.itwmw.com/badge/Test%20Coverage-100%25-brightgreen) -![Download](https://icon.itwmw.com/packagist/dt/w7/engine-validate?style=social&logo=packagist) +
    +

    微擎表单验证

    + Stars + Forks +
    + License + PHP Version Support + Coverity + Tests + Download +
    +
    + ## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 @@ -207,3 +212,10 @@ protected $bail = true; ```php protected bool $filled = true; ``` +### $regex +预定义正则表达式验证规则,详情查看[正则表达式规则](https://v.neww7.com/3/Rule.html#%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%84%E5%88%99) +```php +protected $regex = [ + 'number' => '/^\d+$/' +]; +``` \ No newline at end of file -- Gitee From 3878788a3a0f971c25d7a59bb9e1b47b6305f6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 18 Sep 2021 17:52:38 +0800 Subject: [PATCH 130/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AF=B4=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9a44027..be83cae 100644 --- a/README.md +++ b/README.md @@ -14,20 +14,17 @@ ## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 -## 说明 -此验证基于`illuminate/validation`做了如下扩展 - -- 可通过类的方式定义一个[验证器](https://v.neww7.com/3/Validate.html) -- 增加[验证场景](https://v.neww7.com/3/Scene.html) -- 增加[规则管理器](https://v.neww7.com/3/RuleManager.html) -- 增加数据[默认值](https://v.neww7.com/3/Default.html) -- 增加数据[过滤器](https://v.neww7.com/3/Filter.html) -- 增加[场景事件](https://v.neww7.com/3/Event.html) -- 修改了[自定义验证规则](https://v.neww7.com/3/Rule.html) -- [自定义消息](https://v.neww7.com/3/Message.html) 增加了对内容的引用 -- 继承集合类增加一个[验证集合](https://v.neww7.com/3/Collection.html) - -> 验证器支持Laravel的内置规则,内置规则文档可查看[规则文档](https://learnku.com/docs/laravel/7.x/validation/5144#c58a91) +> 此验证基于`illuminate/validation`扩展,验证器支持Laravel的内置规则,内置规则文档可查看[规则文档](https://learnku.com/docs/laravel/7.x/validation/5144#c58a91) +## 目录 +- [验证器](https://v.neww7.com/3/Validate.html) +- [验证场景](https://v.neww7.com/3/Scene.html) +- [场景事件](https://v.neww7.com/3/Event.html) +- [规则管理器](https://v.neww7.com/3/RuleManager.html) +- [自定义验证规则](https://v.neww7.com/3/Rule.html) +- [自定义消息](https://v.neww7.com/3/Message.html) +- [默认值](https://v.neww7.com/3/Default.html) +- [过滤器](https://v.neww7.com/3/Filter.html) +- [验证集合](https://v.neww7.com/3/Collection.html) ## 安装 使用composer命令 -- Gitee From a44167457ad61d520dcd8483dca0f0f722fbff1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 27 Sep 2021 11:02:07 +0800 Subject: [PATCH 131/152] =?UTF-8?q?[U]=20=E9=A1=B9=E7=9B=AE=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=E5=A2=9E=E5=8A=A0=E8=AE=B8=E5=8F=AF=E8=AF=81=E6=89=AB?= =?UTF-8?q?=E6=8F=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be83cae..0e9fb93 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@
    License PHP Version Support - Coverity + FOSSA Status Tests Download
    -- Gitee From 597663491975cc93486a084e5377fbcef0a57683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Mon, 27 Sep 2021 16:34:14 +0800 Subject: [PATCH 132/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E4=B8=AD=E6=8C=87=E5=AE=9A=E7=9A=84=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=EF=BC=8C=E5=8D=B3=E6=97=B6=E4=B8=8D=E5=AE=9A=E4=B9=89=E8=A7=84?= =?UTF-8?q?=E5=88=99=EF=BC=8C=E4=B9=9F=E5=B0=86=E8=BF=9B=E8=A1=8C=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=20close=20#I4BQJ1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 2 +- src/Support/Common.php | 14 ++++++++++ src/Support/RuleManagerScene.php | 2 +- src/Validate.php | 13 +++++----- tests/Test/TestValidateScene.php | 44 ++++++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index 55655a9..4ffc023 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -469,7 +469,7 @@ class RuleManager $rules = $this->getInitialRules(); if (null !== $field) { $field = is_array($field) ? $field : [$field]; - $rules = array_intersect_key($rules, array_flip($field)); + $rules = Common::getRulesAndFill($rules, $field); } if (false === $initial) { diff --git a/src/Support/Common.php b/src/Support/Common.php index 18f1711..3996a86 100644 --- a/src/Support/Common.php +++ b/src/Support/Common.php @@ -54,4 +54,18 @@ class Common } return $fieldName . '.' . $rule; } + + /** + * Get rules for a given field and populate non-existent fields + * + * @param array $rules + * @param array $fields + * @return array + */ + public static function getRulesAndFill(array $rules, array $fields): array + { + $rules = array_intersect_key($rules, array_flip($fields)); + $notExist = array_diff($fields, array_keys($rules)); + return array_merge($rules, array_fill_keys($notExist, [])); + } } diff --git a/src/Support/RuleManagerScene.php b/src/Support/RuleManagerScene.php index 690f920..67c6813 100644 --- a/src/Support/RuleManagerScene.php +++ b/src/Support/RuleManagerScene.php @@ -45,7 +45,7 @@ class RuleManagerScene implements SceneInterface /** @inheritDoc */ public function only(array $fields): SceneInterface { - $this->checkRules = array_intersect_key($this->rules, array_flip($fields)); + $this->checkRules = Common::getRulesAndFill($this->rules, $fields); return $this; } diff --git a/src/Validate.php b/src/Validate.php index f05137c..3786d18 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -19,6 +19,7 @@ use Illuminate\Validation\ValidationData; use Illuminate\Validation\ValidationException; use W7\Validate\Exception\ValidateException; use W7\Validate\Exception\ValidateRuntimeException; +use W7\Validate\Support\Common; use W7\Validate\Support\Concerns\DefaultInterface; use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Concerns\MessageProviderInterface; @@ -141,9 +142,9 @@ class Validate extends RuleManager */ private $validateFields = []; - /** - * {@inheritdoc } - */ + /** + * {@inheritdoc } + */ protected $sceneProvider = ValidateScene::class; /** @@ -327,10 +328,10 @@ class Validate extends RuleManager if (isset($sceneRule['next']) && !empty($sceneRule['next'])) { $next = $sceneRule['next']; unset($sceneRule['next']); - $rules = array_intersect_key($this->rule, array_flip($sceneRule)); + $rules = Common::getRulesAndFill($this->rule, $sceneRule); return $this->next($next, $rules, $sceneName); } else { - return array_intersect_key($this->rule, array_flip($sceneRule)); + return Common::getRulesAndFill($this->rule, $sceneRule); } } @@ -361,7 +362,7 @@ class Validate extends RuleManager if (method_exists($this, lcfirst($next) . 'Selector')) { $next = call_user_func([$this, lcfirst($next) . 'Selector'], $this->validatedData); if (is_array($next)) { - return array_intersect_key($this->rule, array_flip($next)); + return Common::getRulesAndFill($this->rule, $next); } } diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index 9efaae7..5099902 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -277,6 +277,9 @@ class TestValidateScene extends BaseTestValidate $this->assertEquals(['required', 'min:1'], array_values($rules['id'])); } + /** + * @test 测试在自定义场景中动态移除字段 + */ public function testRemoveCheckField() { $v = new class extends Validate { @@ -297,4 +300,45 @@ class TestValidateScene extends BaseTestValidate $rules = $v->scene('test')->getRules(); $this->assertEquals(['user'], array_keys($rules)); } + + /** + * @test 测试当场景指定的字段没有定义规则 + * @throws ValidateException + */ + public function testSpecifyFieldUndefinedRule() + { + $v = new class extends Validate { + protected $scene = [ + 'login' => ['user', 'pass'] + ]; + }; + + $data = $v->scene('login')->check([ + 'user' => 1, + 'pass' => 2 + ]); + + $this->assertEquals(['user', 'pass'], array_keys($data)); + } + + /** + * 测试当自定义场景中指定的字段没有定义规则 + * @throws ValidateException + */ + public function testSpecifyFieldUndefinedRuleForCustomScene() + { + $v = new class extends Validate { + protected function sceneLogin(ValidateScene $scene) + { + $scene->only(['user', 'pass']); + } + }; + + $data = $v->scene('login')->check([ + 'user' => 1, + 'pass' => 2 + ]); + + $this->assertEquals(['user', 'pass'], array_keys($data)); + } } -- Gitee From 422971e1499871f8d18600ee976a81815ed887a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 8 Oct 2021 14:27:59 +0800 Subject: [PATCH 133/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 20 ++- src/Exception/ValidateException.php | 10 +- src/RuleManager.php | 2 +- .../Concerns/MessageProviderInterface.php | 6 +- src/Support/MessageProvider.php | 16 +- src/Support/Rule/RuleInterface.php | 2 +- src/Support/Storage/ValidateCollection.php | 155 ------------------ src/Support/Storage/ValidateConfig.php | 56 +------ src/Support/ValidateScene.php | 4 +- src/Support/helpers.php | 13 -- src/Validate.php | 21 +-- tests/Material/ArticleValidate.php | 5 +- tests/Material/BaseTestValidate.php | 19 +-- tests/Test/TestCustomMessageProvider.php | 3 - tests/Test/TestCustomRuleAndMessage.php | 4 +- tests/Test/TestValidateScene.php | 22 ++- tests/Test/TestValidateSceneNextAndEvent.php | 4 +- 17 files changed, 72 insertions(+), 290 deletions(-) delete mode 100644 src/Support/Storage/ValidateCollection.php diff --git a/composer.json b/composer.json index 813ad64..4da7efa 100644 --- a/composer.json +++ b/composer.json @@ -17,12 +17,19 @@ "validator", "form validate" ], + "repositories": [ + { + "name": "itwmw/validation", + "type": "path", + "symlink": true, + "url": "../itwmw-validation" + } + ], "require": { "php": "^7.2.5|^8.0|^8.1", - "illuminate/validation": "^6.0|^7.0|^8.0" + "itwmw/validation": "dev-master" }, "require-dev": { - "laravel-lang/lang": "*", "phpunit/phpunit": "^8|^9", "friendsofphp/php-cs-fixer": "^3.0" }, @@ -49,6 +56,13 @@ "providers": [ "W7\\Validate\\Providers\\Laravel\\ValidateProvider" ] + }, + "think": { + "services": [ + "W7\\Validate\\Providers\\Think\\ValidateService" + ] } - } + }, + "minimum-stability": "dev", + "prefer-stable": true } diff --git a/src/Exception/ValidateException.php b/src/Exception/ValidateException.php index 8630015..8ab9e10 100644 --- a/src/Exception/ValidateException.php +++ b/src/Exception/ValidateException.php @@ -17,16 +17,16 @@ use Throwable; class ValidateException extends Exception { - protected $data = []; + protected $attribute; - public function __construct($message = '', $code = 0, array $data = [], Throwable $previous = null) + public function __construct($message = '', $code = 0, string $attribute = '', Throwable $previous = null) { - $this->data = $data; + $this->attribute = $attribute; parent::__construct($message, $code, $previous); } - public function getData(): array + public function getAttribute(): string { - return $this->data; + return $this->attribute; } } diff --git a/src/RuleManager.php b/src/RuleManager.php index 4ffc023..4be9863 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -13,11 +13,11 @@ namespace W7\Validate; use Closure; -use Illuminate\Contracts\Validation\ImplicitRule; use W7\Validate\Support\Common; use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\RuleManagerScene; use W7\Validate\Support\Storage\ValidateConfig; +use W7\Validation\Support\Interfaces\ImplicitRule; /** * @link https://v.neww7.com/en/3/RuleManager.html#introduction diff --git a/src/Support/Concerns/MessageProviderInterface.php b/src/Support/Concerns/MessageProviderInterface.php index 62084d4..f98f250 100644 --- a/src/Support/Concerns/MessageProviderInterface.php +++ b/src/Support/Concerns/MessageProviderInterface.php @@ -19,10 +19,10 @@ interface MessageProviderInterface /** * Handling a message * - * @param string|string[]$messages - * @return string|string[] + * @param string $messages + * @return string */ - public function handleMessage($messages); + public function handleMessage(string $messages): string; /** * Get a validation message for the processed attributes and rules. diff --git a/src/Support/MessageProvider.php b/src/Support/MessageProvider.php index 9f3716f..51ad251 100644 --- a/src/Support/MessageProvider.php +++ b/src/Support/MessageProvider.php @@ -12,9 +12,9 @@ namespace W7\Validate\Support; -use Illuminate\Support\Arr; use W7\Validate\RuleManager; use W7\Validate\Support\Concerns\MessageProviderInterface; +use Itwmw\Validation\Support\Arr; class MessageProvider implements MessageProviderInterface { @@ -79,20 +79,8 @@ class MessageProvider implements MessageProviderInterface } /** @inheritDoc */ - public function handleMessage($messages) + public function handleMessage(string $messages): string { - if (is_array($messages)) { - foreach ($messages as &$errorMessages) { - if (is_array($errorMessages)) { - $errorMessages = array_map([$this, 'replacingFieldsInMessage'], $errorMessages); - } else { - $errorMessages = $this->replacingFieldsInMessage($errorMessages); - } - } - - return $messages; - } - return $this->replacingFieldsInMessage($messages); } diff --git a/src/Support/Rule/RuleInterface.php b/src/Support/Rule/RuleInterface.php index 8f21517..71d7d99 100644 --- a/src/Support/Rule/RuleInterface.php +++ b/src/Support/Rule/RuleInterface.php @@ -12,7 +12,7 @@ namespace W7\Validate\Support\Rule; -use Illuminate\Contracts\Validation\Rule; +use Itwmw\Validation\Support\Interfaces\Rule; interface RuleInterface extends Rule { diff --git a/src/Support/Storage/ValidateCollection.php b/src/Support/Storage/ValidateCollection.php deleted file mode 100644 index 88e7fa4..0000000 --- a/src/Support/Storage/ValidateCollection.php +++ /dev/null @@ -1,155 +0,0 @@ - - * - * This is not a free software - * Using it under the license terms - * visited https://www.w7.cc for more details - */ - -namespace W7\Validate\Support\Storage; - -use ArrayAccess; -use Closure; -use Illuminate\Support\Arr; -use Illuminate\Support\Collection; -use Illuminate\Support\HigherOrderWhenProxy; -use Illuminate\Support\Str; - -/** - * Validator collection is a subclass of Illuminate\Support\Collection - * - * @link https://v.neww7.com/en/3/Collection.html#description - */ -class ValidateCollection extends Collection -{ - /** - * Determine if an item exists in the collection by key. - * - * @link https://v.neww7.com/en/3/Collection.html#has - * @param mixed $key - * @return bool - */ - public function has($key): bool - { - $keys = is_array($key) ? $key : func_get_args(); - - foreach ($keys as $value) { - if (!Arr::has($this->items, $value)) { - return false; - } - } - - return true; - } - - /** - * Execute when the specified field exists - * - * @link https://v.neww7.com/en/3/Collection.html#whenhas - * @param mixed $key Fields to be validated - * @param callable $callback Methods of execution - * @param callable|null $default Methods to execute when not present - * @return HigherOrderWhenProxy|mixed|ValidateCollection - */ - public function whenHas($key, callable $callback, callable $default = null) - { - return $this->when($this->has($key), $callback, $default); - } - - /** - * Execute when the specified field does not exist - * - * @link https://v.neww7.com/en/3/Collection.html#whennothas - * @param mixed $key Fields to be validated - * @param callable $callback Methods to execute when not present - * @param callable|null $default Methods of execution - * @return HigherOrderWhenProxy|mixed|ValidateCollection - */ - public function whenNotHas($key, callable $callback, callable $default = null) - { - return $this->when(!$this->has($key), $callback, $default); - } - - /** - * Get an item from the collection by key. - * - * @link https://v.neww7.com/en/3/Collection.html#get - * @param mixed $key Field Name - * @param mixed|Closure|null $default Default Value - * @return array|ArrayAccess|mixed - */ - public function get($key, $default = null) - { - if (Str::contains($key, '*')) { - $explicitPath = rtrim(explode('*', $key)[0], '.') ?: null; - $results = []; - $_default = rand(1e+5, 1e+10) . time(); - $_value = Arr::get($this->items, $explicitPath, $_default); - - if ($_default !== $_value) { - Arr::set($results, $explicitPath, $_value); - } - - data_set($results, $key, null, true); - - $results = Arr::dot($results); - - $keys = []; - - $pattern = str_replace('\*', '[^\.]+', preg_quote($key)); - - foreach ($results as $_key => $_value) { - if (preg_match('/^' . $pattern . '/', $_key, $matches)) { - $keys[] = $matches[0]; - } - } - - $value = []; - $keys = array_unique($keys); - - foreach ($keys as $key) { - $value[] = Arr::get($this->items, $key); - } - - $value = $value ?: value($default); - } elseif (false !== strpos($key, '.')) { - $value = Arr::get($this->items, $key, $default); - } else { - $value = parent::get($key, $default); - } - - return $value; - } - - /** - * Write the specified value in the collection - * - * @link https://v.neww7.com/en/3/Collection.html#set - * @param mixed $key - * @param mixed $value - * @return $this - */ - public function set($key, $value): ValidateCollection - { - Arr::set($this->items, $key, $value); - return $this; - } - - public function __get($key) - { - if (array_key_exists($key, $this->items)) { - return $this->offsetGet($key); - } - - return parent::__get($key); - } - - public function __set($key, $value) - { - $this->offsetSet($key, $value); - } -} diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index eef17d5..1b82b1c 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -12,14 +12,9 @@ namespace W7\Validate\Support\Storage; -use Composer\Autoload\ClassLoader; -use Illuminate\Contracts\Container\Container; -use Illuminate\Contracts\Translation\Translator; -use Illuminate\Filesystem\Filesystem; -use Illuminate\Translation\FileLoader; -use Illuminate\Validation\Factory; -use Illuminate\Validation\PresenceVerifierInterface; -use ReflectionClass; +use Itwmw\Validation\Factory; +use Itwmw\Validation\Support\Interfaces\PresenceVerifierInterface; +use Itwmw\Validation\Support\Translation\Interfaces\Translator; final class ValidateConfig { @@ -35,12 +30,6 @@ final class ValidateConfig */ protected $translator; - /** - * Containers - * @var Container - */ - protected $container; - /** * Validator Factory * @var Factory @@ -85,7 +74,7 @@ final class ValidateConfig public function getFactory(): Factory { if (empty($this->factory)) { - $this->factory = new Factory($this->getTranslator(), $this->getContainer()); + $this->factory = new Factory($this->getTranslator()); if ($this->getPresenceVerifier()) { $this->factory->setPresenceVerifier($this->getPresenceVerifier()); } @@ -116,28 +105,6 @@ final class ValidateConfig return $this->verifier ?? null; } - /** - * Provide containers - * - * @param Container $container - * @return ValidateConfig - */ - public function setContainer(Container $container): ValidateConfig - { - $this->container = $container; - return $this; - } - - /** - * Get container - * - * @return Container|null - */ - private function getContainer(): ?Container - { - return $this->container ?? null; - } - /** * Provide translator * @@ -155,21 +122,8 @@ final class ValidateConfig * * @return Translator */ - private function getTranslator(): Translator + private function getTranslator(): ?Translator { - if (empty($this->translator)) { - $reflection = new ReflectionClass(ClassLoader::class); - $vendorDir = dirname($reflection->getFileName(), 2); - $langPath = $vendorDir . DIRECTORY_SEPARATOR . 'laravel-lang' . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR; - if (file_exists($langPath . 'locales')) { - $langPath .= 'locales'; - } else { - $langPath .= 'src'; - } - $loader = new FileLoader(new Filesystem(), $langPath); - return new \Illuminate\Translation\Translator($loader, 'zh_CN'); - } - return $this->translator; } diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index cf08614..8527aae 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -13,12 +13,12 @@ namespace W7\Validate\Support; use Closure; -use Illuminate\Support\Arr; +use Itwmw\Validation\Support\Arr; use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\Concerns\DefaultInterface; use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Rule\BaseRule; -use W7\Validate\Support\Storage\ValidateCollection; +use Itwmw\Validation\Support\Collection\Collection as ValidateCollection; /** * Scene classes for validators diff --git a/src/Support/helpers.php b/src/Support/helpers.php index 202222e..4a371b9 100644 --- a/src/Support/helpers.php +++ b/src/Support/helpers.php @@ -10,16 +10,3 @@ * visited https://www.w7.cc for more details */ -use W7\Validate\Support\Storage\ValidateCollection; - -if (!function_exists('validate_collect')) { - /** - * Create a ValidateCollection from the given value. - * @param null $value - * @return ValidateCollection - */ - function validate_collect($value = null): ValidateCollection - { - return new ValidateCollection($value); - } -} diff --git a/src/Validate.php b/src/Validate.php index 3786d18..8a4bc1a 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -13,10 +13,10 @@ namespace W7\Validate; use Closure; -use Illuminate\Support\Str; -use Illuminate\Validation\Factory; -use Illuminate\Validation\ValidationData; -use Illuminate\Validation\ValidationException; +use Itwmw\Validation\Factory; +use Itwmw\Validation\Support\Str; +use Itwmw\Validation\ValidationData; +use Itwmw\Validation\Support\ValidationException; use W7\Validate\Exception\ValidateException; use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\Common; @@ -26,7 +26,7 @@ use W7\Validate\Support\Concerns\MessageProviderInterface; use W7\Validate\Support\DataAttribute; use W7\Validate\Support\Event\ValidateEventAbstract; use W7\Validate\Support\MessageProvider; -use W7\Validate\Support\Storage\ValidateCollection; +use Itwmw\Validation\Support\Collection\Collection as ValidateCollection; use W7\Validate\Support\Storage\ValidateConfig; use W7\Validate\Support\ValidateScene; @@ -195,15 +195,8 @@ class Validate extends RuleManager $this->handleEvent($data, 'afterValidate'); return $data; } catch (ValidationException $e) { - $errors = $this->getMessageProvider()->handleMessage($e->errors()); - $errorMessage = ''; - - foreach ($errors as $message) { - $errorMessage = $message[0]; - break; - } - - throw new ValidateException($errorMessage, 403, $errors, $e); + $error = $this->getMessageProvider()->handleMessage($e->getMessage()); + throw new ValidateException($error, 403, $e->getAttribute(), $e); } } diff --git a/tests/Material/ArticleValidate.php b/tests/Material/ArticleValidate.php index 6aece9f..3379ef7 100644 --- a/tests/Material/ArticleValidate.php +++ b/tests/Material/ArticleValidate.php @@ -20,7 +20,7 @@ class ArticleValidate extends Validate protected $rule = [ 'id' => 'required|numeric', 'content' => 'required|between:1,2000', - 'title' => 'required|between:4,50|alpha|checkTitle', + 'title' => 'required|between:4,50|chs|checkTitle', 'type' => 'required|numeric', ]; @@ -31,7 +31,8 @@ class ArticleValidate extends Validate 'content.digits_between' => '文章长度为1~2000个字符', 'title.required' => '文章标题必须填写', 'title.digits_between' => '文章标题格式错误', - 'title.alpha' => '文章标题长度为4~50个字符', + 'title.between' => '文章标题长度为4~50个字符', + 'title.chs' => '文章标题只能为中文', 'type.required' => '文章分类必须填写', 'type.numeric' => '文章分类错误', 'title.checkTitle' => '有错误啦' diff --git a/tests/Material/BaseTestValidate.php b/tests/Material/BaseTestValidate.php index 7c4913c..5deccac 100644 --- a/tests/Material/BaseTestValidate.php +++ b/tests/Material/BaseTestValidate.php @@ -12,28 +12,17 @@ namespace W7\Tests\Material; -use Illuminate\Filesystem\Filesystem; -use Illuminate\Translation\FileLoader; -use Illuminate\Translation\Translator; use PHPUnit\Framework\TestCase; use W7\Validate\Support\Storage\ValidateConfig; +use Itwmw\Validation\Factory; class BaseTestValidate extends TestCase { public function __construct($name = null, array $data = [], $dataName = '') { - $langPath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'laravel-lang' . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR; - if (file_exists($langPath . 'locales')) { - $langPath .= 'locales'; - } else { - $langPath .= 'src'; - } - - $loader = new FileLoader(new Filesystem(), $langPath); - $translator = new Translator($loader, 'zh_CN'); - - ValidateConfig::instance()->setTranslator($translator); - ValidateConfig::instance()->setRulesPath('W7\\Tests\\Material\\Rules\\'); + $factory = new Factory(); + ValidateConfig::instance()->setFactory($factory) + ->setRulesPath('W7\\Tests\\Material\\Rules\\'); parent::__construct($name, $data, $dataName); } diff --git a/tests/Test/TestCustomMessageProvider.php b/tests/Test/TestCustomMessageProvider.php index cd83fa9..d8f7f9d 100644 --- a/tests/Test/TestCustomMessageProvider.php +++ b/tests/Test/TestCustomMessageProvider.php @@ -56,8 +56,5 @@ class TestCustomMessageProvider extends BaseTestValidate $message = $messageProvider->handleMessage('@{user}:{:user},@{pass}:{:pass}'); $this->assertEquals('账号:admin,密码:123456', $message); - - $message = $messageProvider->handleMessage(['@{user}:{:user},@{pass}:{:pass}']); - $this->assertEquals(['账号:admin,密码:123456'], $message); } } diff --git a/tests/Test/TestCustomRuleAndMessage.php b/tests/Test/TestCustomRuleAndMessage.php index ab98414..da8fc4a 100644 --- a/tests/Test/TestCustomRuleAndMessage.php +++ b/tests/Test/TestCustomRuleAndMessage.php @@ -12,8 +12,8 @@ namespace W7\Tests\Test; -use Illuminate\Contracts\Validation\ImplicitRule; -use Illuminate\Support\Arr; +use Itwmw\Validation\Support\Interfaces\ImplicitRule; +use Itwmw\Validation\Support\Arr; use W7\Tests\Material\BaseTestValidate; use W7\Tests\Material\Rules\Length; use W7\Validate\Exception\ValidateException; diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index 5099902..cf458dd 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -39,8 +39,7 @@ class TestSomeTimes extends Validate protected function sceneTestSomeTimesMultiField(ValidateScene $scene) { - $scene->appendCheckField('b') - ->appendCheckField('a') + $scene->only(['a', 'b']) ->sometimes(['a', 'b'], 'required', function () { return true; }); @@ -132,7 +131,14 @@ class TestValidateScene extends BaseTestValidate try { $v->scene('notFount')->check([]); } catch (ValidateException $e) { - $this->assertCount(2, $e->getData()); + $this->assertSame('user', $e->getAttribute()); + } + try { + $v->scene('notFount')->check([ + 'user' => 123 + ]); + } catch (ValidateException $e) { + $this->assertSame('pass', $e->getAttribute()); } } @@ -166,7 +172,15 @@ class TestValidateScene extends BaseTestValidate try { $v->scene('testSomeTimesMultiField')->check([]); } catch (ValidateException $e) { - $this->assertCount(2, $e->getData()); + $this->assertSame('a', $e->getAttribute()); + } + + try { + $v->scene('testSomeTimesMultiField')->check([ + 'a' => 123 + ]); + } catch (ValidateException $e) { + $this->assertSame('b', $e->getAttribute()); } } diff --git a/tests/Test/TestValidateSceneNextAndEvent.php b/tests/Test/TestValidateSceneNextAndEvent.php index eb65470..ebe1871 100644 --- a/tests/Test/TestValidateSceneNextAndEvent.php +++ b/tests/Test/TestValidateSceneNextAndEvent.php @@ -214,7 +214,7 @@ class TestValidateSceneNextAndEvent extends BaseTestValidate ]); } catch (ValidateException $e) { - $this->assertArrayHasKey('b', $e->getData()); + $this->assertSame('b', $e->getAttribute()); } try { @@ -222,7 +222,7 @@ class TestValidateSceneNextAndEvent extends BaseTestValidate 'b' => '123' ]); } catch (ValidateException $e) { - $this->assertArrayHasKey('c', $e->getData()); + $this->assertSame('c', $e->getAttribute()); } $data = $v->scene('testA')->check([ -- Gitee From 1df52fb08389979b513a0ddce488cea6296be5c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 8 Oct 2021 14:29:02 +0800 Subject: [PATCH 134/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 0e9fb93..21966f8 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ ## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 -> 此验证基于`illuminate/validation`扩展,验证器支持Laravel的内置规则,内置规则文档可查看[规则文档](https://learnku.com/docs/laravel/7.x/validation/5144#c58a91) ## 目录 - [验证器](https://v.neww7.com/3/Validate.html) - [验证场景](https://v.neww7.com/3/Scene.html) -- Gitee From 841349187f6c66f228be1cf46944cf80823a18af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 8 Oct 2021 14:46:33 +0800 Subject: [PATCH 135/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=80=82?= =?UTF-8?q?=E7=94=A8=E4=BA=8EThinkPHP=E6=A1=86=E6=9E=B6=E7=9A=84=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E9=AA=8C=E8=AF=81=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Providers/Think/PresenceVerifier.php | 69 ++++++++++++++++++++++++ src/Providers/Think/ValidateService.php | 28 ++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/Providers/Think/PresenceVerifier.php create mode 100644 src/Providers/Think/ValidateService.php diff --git a/src/Providers/Think/PresenceVerifier.php b/src/Providers/Think/PresenceVerifier.php new file mode 100644 index 0000000..cbfa36f --- /dev/null +++ b/src/Providers/Think/PresenceVerifier.php @@ -0,0 +1,69 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Providers\Think; + +use think\facade\Db; +use Itwmw\Validation\Support\Interfaces\PresenceVerifierInterface; + +class PresenceVerifier implements PresenceVerifierInterface +{ + protected $db; + + public function __construct() + { + $this->db = Db::newQuery(); + } + + public function setConnection(?string $connection) + { + if (!empty($connection)) { + $this->db->connect($connection); + } + } + + public function table(string $table): PresenceVerifierInterface + { + $this->db->table($table); + return $this; + } + + public function where(string $column, $operator = null, $value = null, string $boolean = 'and'): PresenceVerifierInterface + { + switch (strtolower($boolean)) { + case 'and': + $this->db->where($column, $operator, $value); + break; + case 'or': + $this->db->whereOr($column, $operator, $value); + break; + case 'xor': + $this->db->whereXor($column, $operator, $value); + break; + default: + throw new \RuntimeException('操作错误'); + } + + return $this; + } + + public function whereIn(string $column, $values, string $boolean = 'and'): PresenceVerifierInterface + { + $this->db->whereIn($column, $values, $boolean); + return $this; + } + + public function count(string $columns = '*'): int + { + return $this->db->count($columns); + } +} diff --git a/src/Providers/Think/ValidateService.php b/src/Providers/Think/ValidateService.php new file mode 100644 index 0000000..57cd70e --- /dev/null +++ b/src/Providers/Think/ValidateService.php @@ -0,0 +1,28 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Providers\Think; + +use Itwmw\Validation\Factory; +use think\facade\Config; +use think\Service; +use W7\Validate\Support\Storage\ValidateConfig; + +class ValidateService extends Service +{ + public function register() + { + $factory = new Factory(null, str_replace('-', '_', Config::get('lang.default_lang'))); + $factory->setPresenceVerifier(new PresenceVerifier()); + ValidateConfig::instance()->setFactory($factory); + } +} -- Gitee From 586a8c6e5c2748771cf645d00d2c5e48eddb54bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 8 Oct 2021 15:27:32 +0800 Subject: [PATCH 136/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E9=80=82?= =?UTF-8?q?=E7=94=A8=E4=BA=8ELaravel=E6=A1=86=E6=9E=B6=E7=9A=84=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E9=AA=8C=E8=AF=81=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Providers/Laravel/PresenceVerifier.php | 55 ++++++++++++++++++++++ src/Providers/Laravel/ValidateProvider.php | 6 ++- 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 src/Providers/Laravel/PresenceVerifier.php diff --git a/src/Providers/Laravel/PresenceVerifier.php b/src/Providers/Laravel/PresenceVerifier.php new file mode 100644 index 0000000..8784a87 --- /dev/null +++ b/src/Providers/Laravel/PresenceVerifier.php @@ -0,0 +1,55 @@ + + * + * This is not a free software + * Using it under the license terms + * visited https://www.w7.cc for more details + */ + +namespace W7\Validate\Providers\Laravel; + +use Illuminate\Database\ConnectionResolverInterface; +use Itwmw\Validation\Support\Interfaces\PresenceVerifierInterface; + +class PresenceVerifier implements PresenceVerifierInterface +{ + protected $db; + + public function __construct(ConnectionResolverInterface $db) + { + $this->db = $db; + } + + public function table(string $table): PresenceVerifierInterface + { + $this->db = $this->db->table($table)->useWritePdo(); + return $this; + } + + public function setConnection($connection) + { + $this->db->connection($connection); + return $this; + } + + public function where(string $column, $operator = null, $value = null, string $boolean = 'and'): PresenceVerifierInterface + { + $this->db->where($column, $operator, $value, $boolean); + return $this; + } + + public function whereIn(string $column, $values, string $boolean = 'and'): PresenceVerifierInterface + { + $this->db->whereIn($column, $values, $boolean); + return $this; + } + + public function count(string $columns = '*'): int + { + return $this->db->count($columns); + } +} diff --git a/src/Providers/Laravel/ValidateProvider.php b/src/Providers/Laravel/ValidateProvider.php index 662705f..43249cf 100644 --- a/src/Providers/Laravel/ValidateProvider.php +++ b/src/Providers/Laravel/ValidateProvider.php @@ -12,14 +12,16 @@ namespace W7\Validate\Providers\Laravel; -use Illuminate\Support\Facades\App; use Illuminate\Support\ServiceProvider; +use Itwmw\Validation\Factory; use W7\Validate\Support\Storage\ValidateConfig; class ValidateProvider extends ServiceProvider { public function boot() { - ValidateConfig::instance()->setFactory(App::make('validator')); + $factory = new Factory(null, str_replace('-', '_', config('app.locale'))); + $factory->setPresenceVerifier(new PresenceVerifier($this->app->get('db'))); + ValidateConfig::instance()->setFactory($factory); } } -- Gitee From e3f32b2258d5e3cc45223d8b510fac038c88afb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 8 Oct 2021 15:28:05 +0800 Subject: [PATCH 137/152] =?UTF-8?q?[D]=20=E5=88=A0=E9=99=A4bail=E8=A7=84?= =?UTF-8?q?=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ----- src/RuleManager.php | 17 ----------------- src/Validate.php | 14 +------------- 3 files changed, 1 insertion(+), 35 deletions(-) diff --git a/README.md b/README.md index 21966f8..4bd2b9a 100644 --- a/README.md +++ b/README.md @@ -193,11 +193,6 @@ protected $filter = [ ]; ``` 关于过滤器的详情请查看[过滤器](https://v.neww7.com/3/Filter.html)一节 -### $bail -是否首次验证失败后停止运行,如果此属性值为`true`,所有规则会自动增加`bail`规则,默认为`true` -```php -protected $bail = true; -``` ### $filled 所有验证的字段在存在时不能为空,如果此属性值为`true`,所有规则会自动增加`filled`规则,默认为`true` diff --git a/src/RuleManager.php b/src/RuleManager.php index 4be9863..73265e1 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -356,23 +356,6 @@ class RuleManager return $rule; } - /** - * Add the `bail` rule - * - * @param array $rules Original Rules - * @return array - */ - protected function addBailRule(array $rules): array - { - foreach ($rules as &$rule) { - if (!in_array('bail', $rule)) { - array_unshift($rule, 'bail'); - } - } - - return $rules; - } - /** * Add the `filled` rule * diff --git a/src/Validate.php b/src/Validate.php index 8a4bc1a..95df82b 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -40,14 +40,6 @@ class Validate extends RuleManager */ protected $event = []; - /** - * Whether to stop running after the first verification failure - * - * @link https://v.neww7.com/en/3/Validate.html#bail - * @var bool - */ - protected $bail = true; - /** * All validated fields cannot be empty when present * @@ -195,7 +187,7 @@ class Validate extends RuleManager $this->handleEvent($data, 'afterValidate'); return $data; } catch (ValidationException $e) { - $error = $this->getMessageProvider()->handleMessage($e->getMessage()); + $error = $this->getMessageProvider()->handleMessage($e->getMessage()); throw new ValidateException($error, 403, $e->getAttribute(), $e); } } @@ -224,10 +216,6 @@ class Validate extends RuleManager $checkRules = $this->addFilledRule($checkRules); } - if ($this->bail) { - $checkRules = $this->addBailRule($checkRules); - } - // Defaults and filters only handle the fields that are being validated now $fields = array_keys($checkRules); $data = $this->handleDefault($data, $fields); -- Gitee From 9607ef8239698635a2d64032d469f4d68fff604c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 8 Oct 2021 17:00:05 +0800 Subject: [PATCH 138/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0`extendImplicit?= =?UTF-8?q?Rule`,`extendDependentRule`=E6=96=B9=E6=B3=95=20[U]=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E9=9D=99=E6=80=81=E6=89=A9=E5=B1=95=E8=A7=84=E5=88=99?= =?UTF-8?q?=E6=96=B9=E6=B3=95=E5=AF=B9=E5=85=A8=E5=B1=80=E6=9C=89=E6=95=88?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E5=86=8D=E6=8C=89=E9=AA=8C=E8=AF=81=E5=99=A8?= =?UTF-8?q?=E5=8C=BA=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 如需在类中扩展普通规则,请使用rule+规则名来定义方法进行扩展 * 如需在类中扩展隐式规则,请使用`extendImplicitRule`方法 * 如需在类中扩展依赖规则,请使用`extendDependentRule`方法 --- src/RuleManager.php | 39 +++++++++++++++++++-------------------- src/Validate.php | 28 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index 73265e1..4018d4d 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -17,7 +17,7 @@ use W7\Validate\Support\Common; use W7\Validate\Support\Rule\BaseRule; use W7\Validate\Support\RuleManagerScene; use W7\Validate\Support\Storage\ValidateConfig; -use W7\Validation\Support\Interfaces\ImplicitRule; +use Itwmw\Validation\Support\Interfaces\ImplicitRule; /** * @link https://v.neww7.com/en/3/RuleManager.html#introduction @@ -270,34 +270,33 @@ class RuleManager */ public static function replacer(string $rule, $replacer) { - if (array_key_exists($rule, self::$extendName)) { - $ruleName = md5(get_called_class() . $rule); - if (in_array($ruleName, self::$extendName[$rule])) { - $rule = $ruleName; - } - } ValidateConfig::instance()->getFactory()->replacer($rule, $replacer); } /** * Register for custom validator extensions * - * @param string $type Type - * @param string $rule Rule Name - * @param Closure|string|array $extension Closure rules, providing four parameters:$attribute, $value, $parameters, $validator - * @param string|null $message Error Messages + * @param string $type Type + * @param string $rule Rule Name + * @param Closure|string|array $extension Closure rules, providing four parameters:$attribute, $value, $parameters, $validator + * @param string|null $message Error Messages + * @param boolean $avoidDuplication Avoid duplication caused by multiple validators with the same rule name */ - private static function validatorExtend(string $type, string $rule, $extension, ?string $message = null) + protected static function validatorExtend(string $type, string $rule, $extension, ?string $message = null, bool $avoidDuplication = false) { - // Multiple rule managers using the same rule will result in the later methods not taking effect. - // So here a unique rule name is generated based on the namespace. - $ruleName = md5(get_called_class() . $rule); + if ($avoidDuplication) { + // Multiple rule managers using the same rule will result in the later methods not taking effect. + // So here a unique rule name is generated based on the namespace. + $ruleName = md5(get_called_class() . $rule); - if (array_key_exists($rule, self::$extendName)) { - array_push(self::$extendName[$rule], $ruleName); - self::$extendName[$rule] = array_unique(self::$extendName[$rule]); + if (array_key_exists($rule, self::$extendName)) { + array_push(self::$extendName[$rule], $ruleName); + self::$extendName[$rule] = array_unique(self::$extendName[$rule]); + } else { + self::$extendName[$rule] = [$ruleName]; + } } else { - self::$extendName[$rule] = [$ruleName]; + $ruleName = $rule; } if (!empty($type)) { @@ -340,7 +339,7 @@ class RuleManager // If it is a class method, register the rule to the rule manager first, // and then process the corresponding error message if (method_exists($this, 'rule' . ucfirst($rule))) { - self::extend($rule, Closure::fromCallable([$this, 'rule' . ucfirst($rule)])); + self::validatorExtend('', $rule, Closure::fromCallable([$this, 'rule' . ucfirst($rule)]), '', true); if ('' !== $param) { $rule = $rule . ':' . $param; diff --git a/src/Validate.php b/src/Validate.php index 95df82b..4fd8e12 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -248,6 +248,34 @@ class Validate extends RuleManager return $data; } + /** + * Add a custom implicit validation rule + * + * @param string $rule Rule Name + * @param Closure|string|array $extension Closure rules, providing four parameters:$attribute, $value, $parameters, $validator + * @param string|null $message Error Message + * @return Validate + */ + protected function extendImplicitRule(string $rule, $extension, ?string $message = null): Validate + { + self::validatorExtend('Implicit', $rule, $extension, $message, true); + return $this; + } + + /** + * Add a custom dependent validation rule. + * + * @param string $rule Rule Name + * @param Closure|string|array $extension Closure rules, providing four parameters:$attribute, $value, $parameters, $validator + * @param string|null $message Error Message + * @return Validate + */ + protected function extendDependentRule(string $rule, $extension, ?string $message = null): Validate + { + self::validatorExtend('Dependent', $rule, $extension, $message, true); + return $this; + } + /** * Get the rules that need to be validation in the scene * -- Gitee From abab7c488d09280e36118198e9ce9d330056b923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 8 Oct 2021 17:01:51 +0800 Subject: [PATCH 139/152] =?UTF-8?q?[U]=20`replacer`=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E5=AF=B9=E9=AA=8C=E8=AF=81=E5=99=A8=E7=B1=BB?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E6=96=B9=E6=B3=95=E8=A7=84=E5=88=99=E7=94=9F?= =?UTF-8?q?=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Test/TestCustomRuleAndMessage.php | 118 ++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/tests/Test/TestCustomRuleAndMessage.php b/tests/Test/TestCustomRuleAndMessage.php index da8fc4a..5d18d4e 100644 --- a/tests/Test/TestCustomRuleAndMessage.php +++ b/tests/Test/TestCustomRuleAndMessage.php @@ -269,4 +269,122 @@ class TestCustomRuleAndMessage extends BaseTestValidate 'a' => 123 ]); } + + /** + * @test 测试全局定义的规则 + * @throws ValidateException + */ + public function testGlobalExtendRule() + { + Validate::extend('sex', function ($attribute, $value) { + return in_array($value, ['男', '女']); + }, '请输入主流性别'); + + $v = new class extends Validate { + protected $rule = [ + 'sex' => 'required|sex' + ]; + }; + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('请输入主流性别'); + $v->check([ + 'sex' => 1 + ]); + } + + /** + * @test 测试当全局规则和类规则名称相同时的优先级处理是否符合预期 + * @depends testGlobalExtendRule + */ + public function testExtendRulePriority() + { + $v = new class extends Validate { + protected $rule = [ + 'sex' => 'required|sex' + ]; + + protected function ruleSex($attribute, $value): bool + { + return in_array($value, [0, 1]); + } + }; + + $data = $v->check([ + 'sex' => 1 + ]); + + $this->assertSame(1, $data['sex']); + } + + /** + * @test 测试在类中使用`extendImplicitRule`方法扩展存在规则 + * @throws ValidateException + */ + public function testExtendImplicitRuleInClass() + { + $v = new class extends Validate { + public function __construct() + { + $this->extendImplicitRule('empty', function ($attribute, $value) { + return !empty($value); + }, ':attribute参数不可为空'); + } + + protected $rule = [ + 'name' => 'empty' + ]; + }; + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('name参数不可为空'); + $v->check([]); + } + + /** + * @test 测试在类中使用`extendDependentRule`方法扩展依赖规则 + */ + public function testExtendDependentRuleInClass() + { + $v = new class extends Validate { + public function __construct() + { + $this->extendDependentRule('contains', function ($attribute, $value, $parameters, $validator) { + return str_contains($value, Arr::get($validator->getData(), $parameters[0])); + }, '不支持该域的邮箱'); + } + + protected $rule = [ + '*.email' => 'contains:*.provider' + ]; + }; + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('不支持该域的邮箱'); + $v->check([ + ['email' => '995645888@qq.com', 'provider' => 'qq.com'], + ['email' => '351409246@qq.com', 'provider' => 'qq.com'], + ['email' => 'admin@itwmw.com', 'provider' => 'qq.com'] + ]); + } + + /** + * @test 测试替换全局规则的错误消息 + * @depends testGlobalExtendRule + */ + public function testReplacerGlobalRuleMessage() + { + Validate::replacer('sex', function () { + return '请输入正确性别'; + }); + + $this->expectException(ValidateException::class); + $this->expectExceptionMessage('请输入正确性别'); + + Validate::make([ + 'sex' => 'required|sex' + ])->check([ + 'sex' => 666 + ]); + } } -- Gitee From a7cba10b8d7ab5fd67ff12625e929c0e250f00c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 9 Oct 2021 14:59:52 +0800 Subject: [PATCH 140/152] =?UTF-8?q?[U]=20=E4=BF=AE=E6=94=B9=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E5=92=8C=E6=9B=B4=E6=96=B0=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 15 +++----------- tests/Test/TestCustomRuleAndMessage.php | 27 ++++++++++++++----------- tests/Test/TestHandlerEvent.php | 8 ++++---- tests/Test/TestHandlerFunction.php | 4 ++-- tests/Test/TestRegexRule.php | 6 +++--- tests/Test/TestValidateMessage.php | 6 +++--- tests/Test/TestValidateScene.php | 6 +++--- tests/Test/TestValidateSceneNext.php | 2 +- 8 files changed, 34 insertions(+), 40 deletions(-) diff --git a/composer.json b/composer.json index 4da7efa..3995fd9 100644 --- a/composer.json +++ b/composer.json @@ -17,21 +17,12 @@ "validator", "form validate" ], - "repositories": [ - { - "name": "itwmw/validation", - "type": "path", - "symlink": true, - "url": "../itwmw-validation" - } - ], "require": { - "php": "^7.2.5|^8.0|^8.1", - "itwmw/validation": "dev-master" + "php": "^7.3|^8.0", + "itwmw/validation": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^8|^9", - "friendsofphp/php-cs-fixer": "^3.0" + "phpunit/phpunit": "^8|^9" }, "autoload": { "psr-4": { diff --git a/tests/Test/TestCustomRuleAndMessage.php b/tests/Test/TestCustomRuleAndMessage.php index 5d18d4e..e0833c2 100644 --- a/tests/Test/TestCustomRuleAndMessage.php +++ b/tests/Test/TestCustomRuleAndMessage.php @@ -131,7 +131,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate ]); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('输入的字符不合格'); + $this->expectExceptionMessageMatches('/^输入的字符不合格$/'); $v->check([ 'id' => 'aaa' @@ -145,7 +145,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate public function testDependentRule() { $this->expectException(ValidateException::class); - $this->expectExceptionMessage('不支持该域的邮箱'); + $this->expectExceptionMessageMatches('/^不支持该域的邮箱$/'); TestDependentRule::make()->check([ ['email' => '995645888@qq.com', 'provider' => 'qq.com'], @@ -161,7 +161,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate public function testImplicitRule() { $this->expectException(ValidateException::class); - $this->expectExceptionMessage('给定的值为空'); + $this->expectExceptionMessageMatches('/^给定的值为空$/'); TestImplicitRule::make()->check([]); } @@ -173,7 +173,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate public function testImplicitRuleForRuleClass() { $this->expectException(ValidateException::class); - $this->expectExceptionMessage('给定的值为空'); + $this->expectExceptionMessageMatches('/^给定的值为空$/'); Validate::make([ 'a' => [ new TestImplicitRuleClass() @@ -188,7 +188,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate public function testExtendRule() { $this->expectException(ValidateException::class); - $this->expectExceptionMessage('绑定手机号不是有效的手机号码'); + $this->expectExceptionMessageMatches('/^绑定手机号不是有效的手机号码$/'); TestExtendRule::make()->check([ 'bind' => 123 ]); @@ -201,7 +201,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate public function testReplacerErrorMessage() { $this->expectException(ValidateException::class); - $this->expectExceptionMessage('绑定手机号是错误的手机号码'); + $this->expectExceptionMessageMatches('/^绑定手机号是错误的手机号码$/'); TestExtendRule::make()->scene('replacerMobileMessage')->check([ 'bind' => 123 ]); @@ -264,7 +264,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate }; $this->expectException(ValidateException::class); - $this->expectExceptionMessage('testErrorMessage'); + $this->expectExceptionMessageMatches('/^testErrorMessage$/'); $v->check([ 'a' => 123 ]); @@ -287,7 +287,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate }; $this->expectException(ValidateException::class); - $this->expectExceptionMessage('请输入主流性别'); + $this->expectExceptionMessageMatches('/^请输入主流性别$/'); $v->check([ 'sex' => 1 ]); @@ -337,7 +337,7 @@ class TestCustomRuleAndMessage extends BaseTestValidate }; $this->expectException(ValidateException::class); - $this->expectExceptionMessage('name参数不可为空'); + $this->expectExceptionMessageMatches('/^name参数不可为空$/'); $v->check([]); } @@ -360,7 +360,8 @@ class TestCustomRuleAndMessage extends BaseTestValidate }; $this->expectException(ValidateException::class); - $this->expectExceptionMessage('不支持该域的邮箱'); + $this->expectExceptionMessageMatches('/^不支持该域的邮箱$/'); + $v->check([ ['email' => '995645888@qq.com', 'provider' => 'qq.com'], ['email' => '351409246@qq.com', 'provider' => 'qq.com'], @@ -375,14 +376,16 @@ class TestCustomRuleAndMessage extends BaseTestValidate public function testReplacerGlobalRuleMessage() { Validate::replacer('sex', function () { - return '请输入正确性别'; + return ':attribute错误,请输入正确性别'; }); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('请输入正确性别'); + $this->expectExceptionMessageMatches('/^性别错误,请输入正确性别$/'); Validate::make([ 'sex' => 'required|sex' + ], [], [ + 'sex' => '性别' ])->check([ 'sex' => 666 ]); diff --git a/tests/Test/TestHandlerEvent.php b/tests/Test/TestHandlerEvent.php index c03d5a7..b30e2fb 100644 --- a/tests/Test/TestHandlerEvent.php +++ b/tests/Test/TestHandlerEvent.php @@ -125,7 +125,7 @@ class TestHandlerEvent extends BaseTestValidate { $v = new TestValidate(); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('不是中文'); + $this->expectExceptionMessageMatches('/^不是中文$/'); $v->scene('errorEvent')->check([ 'name' => 123 ]); @@ -142,7 +142,7 @@ class TestHandlerEvent extends BaseTestValidate $v->check([]); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('该操作已完成'); + $this->expectExceptionMessageMatches('/^该操作已完成$/'); $v->check([]); } @@ -151,7 +151,7 @@ class TestHandlerEvent extends BaseTestValidate { $v = new TestValidate(); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('用户名不是admin'); + $this->expectExceptionMessageMatches('/^用户名不是admin$/'); $v->scene('checkName')->check([ 'name' => 123 ]); @@ -161,7 +161,7 @@ class TestHandlerEvent extends BaseTestValidate { $v = new TestValidate(); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('error'); + $this->expectExceptionMessageMatches('/^error$/'); $v->scene('beforeThrowError')->check([]); } diff --git a/tests/Test/TestHandlerFunction.php b/tests/Test/TestHandlerFunction.php index b592b4c..35dcd0d 100644 --- a/tests/Test/TestHandlerFunction.php +++ b/tests/Test/TestHandlerFunction.php @@ -40,7 +40,7 @@ class TestHandlerFunction extends BaseTestValidate }; $this->expectException(ValidateException::class); - $this->expectExceptionMessage('ID错误'); + $this->expectExceptionMessageMatches('/^ID错误$/'); $v->scene('testAfter')->check(['id' => -1]); } @@ -63,7 +63,7 @@ class TestHandlerFunction extends BaseTestValidate }; $this->expectException(ValidateException::class); - $this->expectExceptionMessage('站点未开启'); + $this->expectExceptionMessageMatches('/^站点未开启$/'); $v->scene('testBefore')->check([]); } diff --git a/tests/Test/TestRegexRule.php b/tests/Test/TestRegexRule.php index d00bc94..c3ddb61 100644 --- a/tests/Test/TestRegexRule.php +++ b/tests/Test/TestRegexRule.php @@ -45,7 +45,7 @@ class TestRegexRule extends BaseTestValidate $this->assertEquals('123', $data['num']); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('给定的值必须是数字'); + $this->expectExceptionMessageMatches('/^给定的值必须是数字$/'); $v->check([ 'num' => 'sss' ]); @@ -72,7 +72,7 @@ class TestRegexRule extends BaseTestValidate }; $this->expectException(ValidateException::class); - $this->expectExceptionMessage('给定的值不可以为纯数字'); + $this->expectExceptionMessageMatches('/^给定的值不可以为纯数字$/'); $v->check([ 'user' => '123' ]); @@ -115,7 +115,7 @@ class TestRegexRule extends BaseTestValidate $this->assertSame(1, $data['status']); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('状态不符合要求'); + $this->expectExceptionMessageMatches('/^状态不符合要求$/'); $v->scene('test')->check([ 'status' => 'close' ]); diff --git a/tests/Test/TestValidateMessage.php b/tests/Test/TestValidateMessage.php index 6d20a26..b9f2fc9 100644 --- a/tests/Test/TestValidateMessage.php +++ b/tests/Test/TestValidateMessage.php @@ -112,7 +112,7 @@ class TestValidateMessage extends BaseTestValidate public function testMessageInSceneEventClosure() { $this->expectException(ValidateException::class); - $this->expectExceptionMessage('用户名必须填写'); + $this->expectExceptionMessageMatches('/^用户名必须填写$/'); $this->testMessage->scene('testSceneEventClosure')->check([]); } @@ -124,7 +124,7 @@ class TestValidateMessage extends BaseTestValidate public function testMessageInSceneEventCallable() { $this->expectException(ValidateException::class); - $this->expectExceptionMessage('密码必须填写'); + $this->expectExceptionMessageMatches('/^密码必须填写$/'); $this->testMessage->scene('testSceneEventCallable')->check([]); } @@ -136,7 +136,7 @@ class TestValidateMessage extends BaseTestValidate public function testMessageInSceneEvent() { $this->expectException(ValidateException::class); - $this->expectExceptionMessage('用户名必须填写'); + $this->expectExceptionMessageMatches('/^用户名必须填写$/'); $this->testMessage->scene('testSceneEvent')->check([]); } } diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index cf458dd..ef04f62 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -98,7 +98,7 @@ class TestValidateScene extends BaseTestValidate public function testUseScene() { $validate = new ArticleValidate(); - $this->expectExceptionMessage('缺少参数:文章Id'); + $this->expectExceptionMessageMatches('/^缺少参数:文章Id$/'); $validate->scene('save')->check($this->userInput); } @@ -157,7 +157,7 @@ class TestValidateScene extends BaseTestValidate $this->assertSame(0, $data['aIsRequired']); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('a不能为空'); + $this->expectExceptionMessageMatches('/^a不能为空$/'); $v->scene('test')->check([ 'aIsRequired' => 1 ]); @@ -211,7 +211,7 @@ class TestValidateScene extends BaseTestValidate Count::assertEquals(1, 'testAppendClosureRule'); $this->expectException(ValidateException::class); - $this->expectExceptionMessage('a必须为数字'); + $this->expectExceptionMessageMatches('/^a必须为数字$/'); $v->scene('test')->check([ 'a' => 'aaa' ]); diff --git a/tests/Test/TestValidateSceneNext.php b/tests/Test/TestValidateSceneNext.php index 58b0087..96989d7 100644 --- a/tests/Test/TestValidateSceneNext.php +++ b/tests/Test/TestValidateSceneNext.php @@ -127,7 +127,7 @@ class TestValidateSceneNext extends BaseTestValidate }; $this->expectException(ValidateRuntimeException::class); - $this->expectExceptionMessage('The scene used cannot be the same as the current scene.'); + $this->expectExceptionMessageMatches('/^The scene used cannot be the same as the current scene.$/'); $v->scene('test')->check([]); } -- Gitee From d9ab7f647fe776c7d26868ff0afb2504e3006b26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 9 Oct 2021 17:00:30 +0800 Subject: [PATCH 141/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8D=E5=BD=93?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E8=A7=84=E5=88=99=E4=B8=BA=E7=A9=BA=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E9=AA=8C=E8=AF=81=E6=95=B0=E6=8D=AE=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E9=80=9A=E8=BF=87=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Validate.php b/src/Validate.php index 4fd8e12..07510e2 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -230,6 +230,8 @@ class Validate extends RuleManager if (!empty($checkRules)) { $data = $this->getValidationFactory()->make($data, $checkRules, $this->message, $this->customAttributes)->validate(); + } else { + $data = []; } $data = array_merge($this->validatedData, $data); -- Gitee From 7e0f40ecb2b271ce6e6c61de09c572733136485e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 9 Oct 2021 17:08:50 +0800 Subject: [PATCH 142/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E5=BD=93=E9=AA=8C=E8=AF=81=E8=A7=84=E5=88=99=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E6=97=B6=E6=9C=80=E5=90=8E=E7=BB=93=E6=9E=9C=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E4=B8=BA=E7=A9=BA=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Test/TestValidateScene.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/Test/TestValidateScene.php b/tests/Test/TestValidateScene.php index ef04f62..ffb5571 100644 --- a/tests/Test/TestValidateScene.php +++ b/tests/Test/TestValidateScene.php @@ -355,4 +355,29 @@ class TestValidateScene extends BaseTestValidate $this->assertEquals(['user', 'pass'], array_keys($data)); } + + /** + * @test 测试当验证规则为空时最后结果是否为空 + * @throws ValidateException + */ + public function testValidateRuleIsEmpty() + { + $v = new class extends Validate { + protected $rule = [ + 'a' => 'required', + 'b' => 'required' + ]; + + protected $scene = [ + 'empty' => [] + ]; + }; + + $data = $v->scene('empty')->check([ + 'a' => 1, + 'c' => 2 + ]); + + $this->assertEmpty($data); + } } -- Gitee From 472c597c8ba5e9c38528608500c0f0f3e5511273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Sat, 9 Oct 2021 17:55:26 +0800 Subject: [PATCH 143/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0=E5=AF=B9?= =?UTF-8?q?=E8=BD=AF=E6=93=8E=E6=A1=86=E6=9E=B6=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Providers/Rangine/ValidateProvider.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Providers/Rangine/ValidateProvider.php b/src/Providers/Rangine/ValidateProvider.php index 1a122df..951663c 100644 --- a/src/Providers/Rangine/ValidateProvider.php +++ b/src/Providers/Rangine/ValidateProvider.php @@ -12,8 +12,11 @@ namespace W7\Validate\Providers\Rangine; +use Itwmw\Validation\Factory; use W7\Core\Provider\ProviderAbstract; +use W7\Facade\Config; use W7\Facade\Container; +use W7\Validate\Providers\Laravel\PresenceVerifier; use W7\Validate\Support\Storage\ValidateConfig; class ValidateProvider extends ProviderAbstract @@ -25,6 +28,8 @@ class ValidateProvider extends ProviderAbstract */ public function boot() { - ValidateConfig::instance()->setFactory(Container::get("W7\Contract\Validation\ValidatorFactoryInterface")); + $factory = new Factory(null, str_replace('-', '_', Config::get('app.setting.lang', 'zh_cn'))); + $factory->setPresenceVerifier(new PresenceVerifier(Container::get('db-factory'))); + ValidateConfig::instance()->setFactory($factory); } } -- Gitee From 424172d13c9795f4db8e31b1338db93be8527d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 12 Oct 2021 16:00:12 +0800 Subject: [PATCH 144/152] =?UTF-8?q?[U]=20=E8=B0=83=E6=95=B4=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Validate.php | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Validate.php b/src/Validate.php index 07510e2..d3c3fc0 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -228,26 +228,24 @@ class Validate extends RuleManager $this->handleEvent($data, 'beforeValidate'); } + $validatedData = $this->validatedData; if (!empty($checkRules)) { - $data = $this->getValidationFactory()->make($data, $checkRules, $this->message, $this->customAttributes)->validate(); - } else { - $data = []; + $validatedData = $this->getValidationFactory()->make($data, $checkRules, $this->message, $this->customAttributes)->validate(); + $validatedData = array_merge($this->validatedData, $validatedData); } - $data = array_merge($this->validatedData, $data); - if ($this->eventPriority) { - $this->handleCallback($data, 2); - $this->handleEvent($data, 'afterValidate'); + $this->handleCallback($validatedData, 2); + $this->handleEvent($validatedData, 'afterValidate'); } else { - $this->handleEvent($data, 'afterValidate'); - $this->handleCallback($data, 2); + $this->handleEvent($validatedData, 'afterValidate'); + $this->handleCallback($validatedData, 2); } - $data = $this->handlerFilter($data, $fields); + $validatedData = $this->handlerFilter($validatedData, $fields); $this->initScene(); $this->scene(null); - return $data; + return $validatedData; } /** -- Gitee From e209f5fb69088fa04f37c4a02a52bb04ad06bd19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 12 Oct 2021 16:18:41 +0800 Subject: [PATCH 145/152] =?UTF-8?q?[U]=20=E4=B8=BA=E4=BF=9D=E6=8C=81?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E4=B8=80=E8=87=B4=EF=BC=8C=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=E7=9A=84=E5=BC=95=E7=94=A8=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E6=94=B9=E4=B8=BA{@attribute}?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/MessageProvider.php | 2 +- tests/Test/TestCustomMessageProvider.php | 2 +- tests/Test/TestValidateMessage.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Support/MessageProvider.php b/src/Support/MessageProvider.php index 51ad251..df0199a 100644 --- a/src/Support/MessageProvider.php +++ b/src/Support/MessageProvider.php @@ -105,7 +105,7 @@ class MessageProvider implements MessageProviderInterface } } - if (preg_match_all('/@{(.*?)}/', $message, $matches) > 0) { + if (preg_match_all('/{@(.*?)}/', $message, $matches) > 0) { foreach ($matches[0] as $index => $pregString) { $message = str_replace($pregString, $this->customAttributes[$matches[1][$index]] ?? '', $message); } diff --git a/tests/Test/TestCustomMessageProvider.php b/tests/Test/TestCustomMessageProvider.php index d8f7f9d..e1ccc3c 100644 --- a/tests/Test/TestCustomMessageProvider.php +++ b/tests/Test/TestCustomMessageProvider.php @@ -54,7 +54,7 @@ class TestCustomMessageProvider extends BaseTestValidate 'pass' => '密码' ]); - $message = $messageProvider->handleMessage('@{user}:{:user},@{pass}:{:pass}'); + $message = $messageProvider->handleMessage('{@user}:{:user},{@pass}:{:pass}'); $this->assertEquals('账号:admin,密码:123456', $message); } } diff --git a/tests/Test/TestValidateMessage.php b/tests/Test/TestValidateMessage.php index b9f2fc9..eeb89db 100644 --- a/tests/Test/TestValidateMessage.php +++ b/tests/Test/TestValidateMessage.php @@ -42,7 +42,7 @@ class TestMessage extends Validate 'user.required' => '用户名必须填写', 'user.email' => '你输入的:{:user},不是有效的:attribute', 'pass.required' => '密码必须填写', - 're_pass.eq' => '你输入的@{pass}与:attribute不一致' + 're_pass.eq' => '你输入的{@pass}与:attribute不一致' ]; protected $customAttributes = [ -- Gitee From 9a36a425ff1af7abf1aebdd6bf6e41aa5caff6ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 12 Oct 2021 17:42:46 +0800 Subject: [PATCH 146/152] =?UTF-8?q?[U]=20=E5=88=A0=E6=8E=89=E4=B8=8D?= =?UTF-8?q?=E5=BF=85=E8=A6=81=E7=9A=84As?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Support/ValidateScene.php | 10 +++++----- src/Validate.php | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Support/ValidateScene.php b/src/Support/ValidateScene.php index 8527aae..91a51ab 100644 --- a/src/Support/ValidateScene.php +++ b/src/Support/ValidateScene.php @@ -18,7 +18,7 @@ use W7\Validate\Exception\ValidateRuntimeException; use W7\Validate\Support\Concerns\DefaultInterface; use W7\Validate\Support\Concerns\FilterInterface; use W7\Validate\Support\Rule\BaseRule; -use Itwmw\Validation\Support\Collection\Collection as ValidateCollection; +use Itwmw\Validation\Support\Collection\Collection; /** * Scene classes for validators @@ -100,7 +100,7 @@ class ValidateScene extends RuleManagerScene * @link https://v.neww7.com/en/3/Scene.html#sometimes * @param string|string[] $attribute field name * @param string|array|BaseRule $rules rules - * @param callable $callback Closure,method provides a {@see ValidateCollection} $data parameter, + * @param callable $callback Closure,method provides a {@see Collection} $data parameter, * which is the current validation data, * if the Closure passed as the third argument returns true, the rules will be added. * @return $this @@ -270,12 +270,12 @@ class ValidateScene extends RuleManagerScene } /** - * Get the current validation data,Return the {@see ValidateCollection} type + * Get the current validation data,Return the {@see Collection} type * * @link https://v.neww7.com/en/3/Scene.html#getvalidatedata - * @return ValidateCollection + * @return Collection */ - public function getValidateData(): ValidateCollection + public function getValidateData(): Collection { return validate_collect($this->getData()); } diff --git a/src/Validate.php b/src/Validate.php index d3c3fc0..5f331bf 100644 --- a/src/Validate.php +++ b/src/Validate.php @@ -26,7 +26,7 @@ use W7\Validate\Support\Concerns\MessageProviderInterface; use W7\Validate\Support\DataAttribute; use W7\Validate\Support\Event\ValidateEventAbstract; use W7\Validate\Support\MessageProvider; -use Itwmw\Validation\Support\Collection\Collection as ValidateCollection; +use Itwmw\Validation\Support\Collection\Collection; use W7\Validate\Support\Storage\ValidateConfig; use W7\Validate\Support\ValidateScene; @@ -498,9 +498,9 @@ class Validate extends RuleManager * * @param string $field Name of the data field to be processed * @param callable|Closure|FilterInterface $callback The filter. This can be a global function name, anonymous function, etc. - * @param ValidateCollection $data + * @param Collection $data */ - private function filterValue(string $field, $callback, ValidateCollection $data) + private function filterValue(string $field, $callback, Collection $data) { if (!$data->has($field)) { return; @@ -563,10 +563,10 @@ class Validate extends RuleManager * * @param string $field Name of the data field to be processed * @param callable|Closure|DefaultInterface|mixed $callback The default value or an anonymous function that returns the default value which will - * @param ValidateCollection $data Data to be processed + * @param Collection $data Data to be processed * @param bool $any Whether to handle arbitrary values, default only handle values that are not null */ - private function setDefaultData(string $field, $callback, ValidateCollection $data, bool $any = false) + private function setDefaultData(string $field, $callback, Collection $data, bool $any = false) { $isEmpty = function ($value) { return null === $value || [] === $value || '' === $value; -- Gitee From cbf6bf7aedd24ddd1829d38890cb51065449c173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Tue, 12 Oct 2021 19:30:44 +0800 Subject: [PATCH 147/152] =?UTF-8?q?[A]=20=E7=B1=BB=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=94=99=E8=AF=AF=E6=B6=88=E6=81=AF=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RuleManager.php | 17 +++++++++++++- src/Support/Storage/ValidateConfig.php | 8 ++++++- tests/Test/TestCustomRuleAndMessage.php | 30 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/RuleManager.php b/src/RuleManager.php index 4018d4d..2600004 100644 --- a/src/RuleManager.php +++ b/src/RuleManager.php @@ -55,6 +55,13 @@ class RuleManager */ protected $message = []; + /** + * Messages for class method rules + * + * @var array + */ + protected $ruleMessage = []; + /** * Regular validation rules * @@ -339,7 +346,15 @@ class RuleManager // If it is a class method, register the rule to the rule manager first, // and then process the corresponding error message if (method_exists($this, 'rule' . ucfirst($rule))) { - self::validatorExtend('', $rule, Closure::fromCallable([$this, 'rule' . ucfirst($rule)]), '', true); + if (array_key_exists(lcfirst($rule), $this->ruleMessage)) { + $message = $this->ruleMessage[lcfirst($rule)]; + } elseif (array_key_exists(ucfirst($rule), $this->ruleMessage)) { + $message = $this->ruleMessage[ucfirst($rule)]; + } else { + $message = ''; + } + + self::validatorExtend('', $rule, Closure::fromCallable([$this, 'rule' . ucfirst($rule)]), $message, true); if ('' !== $param) { $rule = $rule . ':' . $param; diff --git a/src/Support/Storage/ValidateConfig.php b/src/Support/Storage/ValidateConfig.php index 1b82b1c..59aaa5d 100644 --- a/src/Support/Storage/ValidateConfig.php +++ b/src/Support/Storage/ValidateConfig.php @@ -74,7 +74,13 @@ final class ValidateConfig public function getFactory(): Factory { if (empty($this->factory)) { - $this->factory = new Factory($this->getTranslator()); + $translator = $this->getTranslator(); + if (is_null($translator)) { + $this->factory = new Factory(); + } else { + $this->factory = new Factory($translator); + } + if ($this->getPresenceVerifier()) { $this->factory->setPresenceVerifier($this->getPresenceVerifier()); } diff --git a/tests/Test/TestCustomRuleAndMessage.php b/tests/Test/TestCustomRuleAndMessage.php index e0833c2..33645ab 100644 --- a/tests/Test/TestCustomRuleAndMessage.php +++ b/tests/Test/TestCustomRuleAndMessage.php @@ -390,4 +390,34 @@ class TestCustomRuleAndMessage extends BaseTestValidate 'sex' => 666 ]); } + + /** + * @test 为类方法规则定义错误消息 + * @throws ValidateException + */ + public function testCustomRuleMessage() + { + $v = new class extends Validate { + protected $ruleMessage = [ + 'isChildren' => '不是未成年' + ]; + + protected $rule = [ + 'age' => 'numeric|isChildren' + ]; + + protected function ruleIsChildren($attribute, $value): bool + { + return $value < 18; + } + }; + + $data = $v->check(['age' => 15]); + $this->assertSame(15, $data['age']); + + $this->expectException(ValidateException::class); + $this->expectExceptionMessageMatches('/^不是未成年$/'); + + $v->check(['age' => 20]); + } } -- Gitee From c9fde24b77487001f2ddeeb35ef94a98347d026b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 13 Oct 2021 18:36:08 +0800 Subject: [PATCH 148/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4bd2b9a..8a0909d 100644 --- a/README.md +++ b/README.md @@ -15,15 +15,15 @@ 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 ## 目录 -- [验证器](https://v.neww7.com/3/Validate.html) -- [验证场景](https://v.neww7.com/3/Scene.html) -- [场景事件](https://v.neww7.com/3/Event.html) -- [规则管理器](https://v.neww7.com/3/RuleManager.html) -- [自定义验证规则](https://v.neww7.com/3/Rule.html) -- [自定义消息](https://v.neww7.com/3/Message.html) -- [默认值](https://v.neww7.com/3/Default.html) -- [过滤器](https://v.neww7.com/3/Filter.html) -- [验证集合](https://v.neww7.com/3/Collection.html) +- [验证器](https://v.neww7.com/4/Validate.html) +- [验证场景](https://v.neww7.com/4/Scene.html) +- [场景事件](https://v.neww7.com/4/Event.html) +- [规则管理器](https://v.neww7.com/4/RuleManager.html) +- [自定义验证规则](https://v.neww7.com/4/Rule.html) +- [自定义消息](https://v.neww7.com/4/Message.html) +- [默认值](https://v.neww7.com/4/Default.html) +- [过滤器](https://v.neww7.com/4/Filter.html) +- [验证集合](https://v.neww7.com/4/Collection.html) ## 安装 使用composer命令 @@ -192,6 +192,14 @@ protected $filter = [ 'name' => 'trim' ]; ``` +### $ruleMessage +类方法规则的错误信息 +```php + protected $ruleMessage = [ + ':attribute的值只能具有中文' +]; +``` +点击查看[示例](https://v.neww7.com/3/Rule.html#%E4%BD%BF%E7%94%A8%E8%A7%84%E5%88%99%E5%AF%B9%E8%B1%A1) 关于过滤器的详情请查看[过滤器](https://v.neww7.com/3/Filter.html)一节 ### $filled 所有验证的字段在存在时不能为空,如果此属性值为`true`,所有规则会自动增加`filled`规则,默认为`true` -- Gitee From 9ff3cca538936e15b42211a6cfb1aa905823db1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 13 Oct 2021 18:39:16 +0800 Subject: [PATCH 149/152] =?UTF-8?q?[U]=20=E6=9B=B4=E6=96=B0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 8a0909d..357fe6c 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ $v->setMessages([ ]); ``` ### $scene -定义验证场景的数据,用于指定验证场景对应的验证字段等,详细用法查看[验证场景](https://v.neww7.com/3/Scene.html)一节,同样也可以通过`setScene`方法来进行设置,此方法为叠加,如果参数为`null`则为清空全部验证场景 +定义验证场景的数据,用于指定验证场景对应的验证字段等,详细用法查看[验证场景](https://v.neww7.com/4/Scene.html)一节,同样也可以通过`setScene`方法来进行设置,此方法为叠加,如果参数为`null`则为清空全部验证场景 ```php // 类中定义 protected $scene = [ @@ -162,7 +162,7 @@ $v->setScene([ ]); ``` ### $event -定义此验证器下的全局事件,详细用法查看[事件](https://v.neww7.com/3/Event.html)一节 +定义此验证器下的全局事件,详细用法查看[事件](https://v.neww7.com/4/Event.html)一节 ```php protected $event = [ CheckSiteStatus::class @@ -170,7 +170,7 @@ protected $event = [ ``` ### $customAttributes 定义验证字段的名称,也可以通过`setCustomAttributes`方法来进行设置,此方法为叠加,如果参数为`null`则为清空全部字段名称, -错误消息中的[:attribute](https://v.neww7.com/3/Message.html#attribute)会使用下面的值对应的替换 +错误消息中的[:attribute](https://v.neww7.com/4/Message.html#attribute)会使用下面的值对应的替换 ```php protected $customAttributes = [ 'user' => '账号', @@ -184,7 +184,7 @@ protected $default = [ 'name' => '张三' ]; ``` -关于默认值的详情请查看[默认值](https://v.neww7.com/3/Default.html)一节 +关于默认值的详情请查看[默认值](https://v.neww7.com/4/Default.html)一节 ### $filter 用于数据验证后处理数据 ```php @@ -192,6 +192,7 @@ protected $filter = [ 'name' => 'trim' ]; ``` +关于过滤器的详情请查看[过滤器](https://v.neww7.com/4/Filter.html)一节 ### $ruleMessage 类方法规则的错误信息 ```php @@ -199,20 +200,19 @@ protected $filter = [ ':attribute的值只能具有中文' ]; ``` -点击查看[示例](https://v.neww7.com/3/Rule.html#%E4%BD%BF%E7%94%A8%E8%A7%84%E5%88%99%E5%AF%B9%E8%B1%A1) -关于过滤器的详情请查看[过滤器](https://v.neww7.com/3/Filter.html)一节 +点击查看[示例](https://v.neww7.com/4/Rule.html#%E4%BD%BF%E7%94%A8%E8%A7%84%E5%88%99%E5%AF%B9%E8%B1%A1) ### $filled 所有验证的字段在存在时不能为空,如果此属性值为`true`,所有规则会自动增加`filled`规则,默认为`true` 当出现以下情况时,不会自动添加`filled`规则 - 验证规则中存在`filled`, `nullable`, `accepted`, `present`,`required`, `required_if`, `required_unless`, `required_with`,`required_with_all`, `required_without`, `required_without_all`规则 -- 验证规则存在[extendImplicit](https://v.neww7.com/3/Rule.html#extendimplicit-隐式扩展)定义的规则 -- 验证规则实现了[ImplicitRule](https://v.neww7.com/3/Rule.html#implicitrule-隐式规则对象)标记接口 +- 验证规则存在[extendImplicit](https://v.neww7.com/4/Rule.html#extendimplicit-隐式扩展)定义的规则 +- 验证规则实现了[ImplicitRule](https://v.neww7.com/4/Rule.html#implicitrule-隐式规则对象)标记接口 ```php protected bool $filled = true; ``` ### $regex -预定义正则表达式验证规则,详情查看[正则表达式规则](https://v.neww7.com/3/Rule.html#%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%84%E5%88%99) +预定义正则表达式验证规则,详情查看[正则表达式规则](https://v.neww7.com/4/Rule.html#%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E8%A7%84%E5%88%99) ```php protected $regex = [ 'number' => '/^\d+$/' -- Gitee From cbdccd16477f71f8502dec2179ecfaa9ca9c852f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Wed, 13 Oct 2021 18:56:28 +0800 Subject: [PATCH 150/152] =?UTF-8?q?[U]=20=E8=A1=A5=E5=85=85=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 357fe6c..8db798f 100644 --- a/README.md +++ b/README.md @@ -206,8 +206,9 @@ protected $filter = [ 当出现以下情况时,不会自动添加`filled`规则 - 验证规则中存在`filled`, `nullable`, `accepted`, `present`,`required`, `required_if`, `required_unless`, `required_with`,`required_with_all`, `required_without`, `required_without_all`规则 -- 验证规则存在[extendImplicit](https://v.neww7.com/4/Rule.html#extendimplicit-隐式扩展)定义的规则 -- 验证规则实现了[ImplicitRule](https://v.neww7.com/4/Rule.html#implicitrule-隐式规则对象)标记接口 +- 验证规则存在[extendImplicit](https://v.neww7.com/4/Rule.html#extendimplicit-%E9%9A%90%E5%BC%8F%E6%89%A9%E5%B1%95)定义的规则 +- 验证规则存在[extendImplicitRule](https://v.neww7.com/4/Rule.html#%E5%AE%9A%E4%B9%89Implicit%E9%AA%8C%E8%AF%81%E5%99%A8)定义的规则 +- 验证规则实现了`Itwmw\Validation\Support\Interfaces\ImplicitRule`标记接口 ```php protected bool $filled = true; ``` -- Gitee From c67123fe4219f8035178fbd8cd381c43e6f91abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Thu, 14 Oct 2021 13:51:56 +0800 Subject: [PATCH 151/152] =?UTF-8?q?[A]=20=E5=A2=9E=E5=8A=A0=E8=8B=B1?= =?UTF-8?q?=E6=96=87=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README-EN.md | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 5 +- 2 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 README-EN.md diff --git a/README-EN.md b/README-EN.md new file mode 100644 index 0000000..29b435c --- /dev/null +++ b/README-EN.md @@ -0,0 +1,240 @@ +
    +

    Micro Engine Form Validate

    + Stars + Forks +
    + License + PHP Version Support + FOSSA Status + Tests + Download +
    +
    + +[中文](https://gitee.com/we7coreteam/w7-engine-validate/blob/4.x/README.md) | +English + +## Introduction +An extension to make your form validation easier, faster and more secure for all your validation needs. + +## Catalog +- [Validator](https://v.neww7.com/en/4/Validate.html) +- [Validate Scene](https://v.neww7.com/en/4/Scene.html) +- [Validate Events](https://v.neww7.com/en/4/Event.html) +- [Rule Manager](https://v.neww7.com/en/4/RuleManager.html) +- [Built-in Rules](https://v.neww7.com/en/4/BuiltRule.html) +- [Custom Rules](https://v.neww7.com/en/4/Rule.html) +- [Custom Error Messages](https://v.neww7.com/en/4/Message.html) +- [Data Default](https://v.neww7.com/en/4/Default.html) +- [Data Filter](https://v.neww7.com/en/4/Filter.html) +- [Validate Collection](https://v.neww7.com/en/4/Collection.html) + +## Install +using Composer +``` shell +composer require w7/engine-validate +``` + +## Simple Validate +Support for simply defining a validator and performing validation: +```php +try { + $data = Validate::make([ + 'user' => 'required|email', + 'pass' => 'required|lengthBetween:6,16', + ], [ + 'user.required' => 'Please enter your username', + 'user.email' => 'User name format error', + 'pass.required' => 'Please enter your password', + 'pass.lengthBetween' => 'Password length is 6~16 bits', + ])->check($data); +} catch (ValidateException $e) { + echo $e->getMessage(); +} +``` +If the validation passes, all values that passed the validation are returned, +if not, a `W7\Validate\Exception\ValidateException` exception is thrown + +## Validator Definition +To define the validator class for a specific validation scenario or data form, we need to inherit the `W7\Validate\Validate` class, +Then instantiate and call the `check` method of the validation class directly to complete the validation, an example of which is as follows. + +Define a `LoginValidate` validator class for login validation. +```php +class LoginValidate extends Validate +{ + protected $rule = [ + 'user' => 'required|email', + 'pass' => 'required|digits_between:6,16', + ]; + + protected $message = [ + 'user.required' => 'Please enter your username', + 'user.email' => 'Incorrect username format', + 'pass.required' => 'Please enter your password', + 'pass.digits_between' => 'Password length of 6 to 16 digits', + ]; +} + +``` +:::tip
    Error messages defined by class attributes take precedence over the default responses in custom rules and over the errors returned by custom rule methods.
    +::: + +## Data Validate +``` php +$data = [ + 'user' => '123@qq.com', + 'pass' => '' +]; +$validate = new LoginValidate(); +$validate->check($data); +``` +This throws a `W7\Validate\Exception\ValidateException` exception with the message `Please enter your password` +``` php +$data = [ + 'user' => '123@qq.com', + 'pass' => '123456' +]; +$validate = new LoginValidate(); +$data = $validate->check($data); +``` +Validates successfully and returns the validated value, which is an array type + +## Validate Arrays +It is not difficult to validate the form input as an array of fields. +You can use the "dot" method to validate properties in an array. +For example, if the incoming HTTP request contains the `search[keyword]` field, +it can be validated as follows. + +``` php +protected $rule = [ + 'search.order' => 'numeric|between:1,2', + 'search.keyword' => 'chsAlphaNum', + 'search.recycle' => 'boolean', +]; +``` +You can also validate each element in an array. For example, to validate that each id in a given array input field is unique, you can do this. + +``` php +protected $rule = [ + 'search.*.id' => 'numeric|unique:account' +]; +``` +The definition of an error message for an array rule is the same + +``` php +protected $message = [ + 'search.order.numeric' => 'order parameter error', + 'search.order.between' => 'order parameter error', + 'search.keyword.chsAlphaNum' => 'Keywords can only contain Chinese, letters, numbers', + 'search.recycle.boolean' => 'Parameter error:recycle', +]; +``` +## Validator Class Attributes +### $rule +The validation rules of the user-defined validator can also be set via the `setRules` method, +This method will superimpose the data.If the parameter is `null` then it is clear all rules. +```php +// Definition in class +protected $rule = [ + 'user' => 'required' +]; + +// Definition of usage methods +$v->setRules([ + 'user' => 'required' +]); +``` +### $message +User-defined validator error messages can also be set via the `setMessages` method, +This method will superimpose the data,If the parameter is `null` then it is clear all error messages. +```php +// Definition in class +protected $message = [ + 'user.required' => 'user is required' +]; + +// Definition of usage methods +$v->setMessages([ + 'user.required' => 'pass is required' +]); +``` +### $scene +Define the data of the validation scenario, which is used to specify the validation fields corresponding to the validation scenario, etc. +See the section on [validate scene](https://v.neww7.com/en/4/Scene.html) for detailed usage. + +The same can be done with the `setScene` method. +This method will superimpose the data, +If the parameter is `null`, then all validate scene are cleared. +```php +// Definition in class +protected $scene = [ + 'login' => ['user', 'pass'] +]; + +// Definition of usage methods +$v->setScene([ + 'login' => ['user', 'pass'] +]); +``` +### $event +Define global events under this validator, see the section [Events](https://v.neww7.com/en/4/Event.html) for detailed usage. +```php +protected $handler = [ + CheckSiteStatus::class +]; +``` +### $default +Defining the default value of a field +```php +protected $default = [ + 'name' => 'Emma' +]; +``` +For more information about default values, please see the section [Default Values](https://v.neww7.com/en/4/Default.html). +### $filter +For processing data after data validation +```php +protected $filter = [ + 'name' => 'trim' +]; +``` +For more information about filters, please see the [Filter](https://v.neww7.com/en/4/Filter.html) section. +### $customAttributes +Define the name of the validation field, also can be set by `setCustomAttributes` method, this method will superimpose the data, +if the parameter is `null` then it is clear all field names. +the [:attribute](https://v.neww7.com/en/4/Message.htm#attribute) in the error message will be replaced with the value corresponding to the following + +```php +protected $customAttributes = [ + 'user' => 'Account', + 'pass' => 'Password' +]; +``` +### $ruleMessage +Error messages for class method rules +```php + protected $ruleMessage = [ + 'The value of :attribute can only have Chinese' +]; +``` +Click to view [example](https://v.neww7.com/en/4/Rule.htm#using-rule-objects) +### $filled +All validated fields cannot be empty when they exist, if the value of this property is `true`, +all rules will automatically add `filled` rules, the default is `true` + +The `filled` rule is not automatically added when: +- Validation rules exist in `filled`, `nullable`, `accepted`, `present`,`required`, `required_if`, `required_unless`, `required_with`,`required_with_all`, `required_without`, `required_without_all` Rule +- Validation rules exist [extendImplicit](https://v.neww7.com/en/4/Rule.htm#extendimplicit) Defined rules +- Validation rules exist [extendImplicitRule](https://v.neww7.com/en/4/Rule.htm#defining-the-implicit-validator) Defined rules +- The validation rules implement the `Itwmw\Validation\Support\Interfaces\ImplicitRule` Marker Interface +```php +protected bool $filled = true; +``` +### $regex +Predefined regular expression validation rules, see [Regular Expression Rule](https://v.neww7.com/en/4/Rule.htm#regular-expression-rule) for details +```php +protected $regex = [ + 'number' => '/^\d+$/' +]; +``` \ No newline at end of file diff --git a/README.md b/README.md index 8db798f..459c393 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,9 @@ +中文 | +[English](https://gitee.com/we7coreteam/w7-engine-validate/blob/4.x/README-EN.md) + ## 介绍 一个让你的表单验证更为方便,快捷,安全的扩展,满足你的一切验证需求。 @@ -19,6 +22,7 @@ - [验证场景](https://v.neww7.com/4/Scene.html) - [场景事件](https://v.neww7.com/4/Event.html) - [规则管理器](https://v.neww7.com/4/RuleManager.html) +- [内置规则](https://v.neww7.com/4/BuiltRule.html) - [自定义验证规则](https://v.neww7.com/4/Rule.html) - [自定义消息](https://v.neww7.com/4/Message.html) - [默认值](https://v.neww7.com/4/Default.html) @@ -33,7 +37,6 @@ composer require w7/engine-validate 完整文档查看[完整文档](https://v.neww7.com) -# 验证器 ## 简单验证 支持简单定义一个验证器并进行验证: ```php -- Gitee From d05470713d33a817c1c886e5b0d2b73c79ecbeca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=99=9E=E7=81=AA?= <995645888@qq.com> Date: Fri, 15 Oct 2021 16:17:00 +0800 Subject: [PATCH 152/152] =?UTF-8?q?[F]=20=E4=BF=AE=E5=A4=8DLaravel?= =?UTF-8?q?=E5=92=8CRangine=E6=A1=86=E6=9E=B6=E7=9A=84=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Providers/Laravel/PresenceVerifier.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Providers/Laravel/PresenceVerifier.php b/src/Providers/Laravel/PresenceVerifier.php index 8784a87..8dee0dc 100644 --- a/src/Providers/Laravel/PresenceVerifier.php +++ b/src/Providers/Laravel/PresenceVerifier.php @@ -19,20 +19,22 @@ class PresenceVerifier implements PresenceVerifierInterface { protected $db; + protected $connectionResolver; + public function __construct(ConnectionResolverInterface $db) { - $this->db = $db; + $this->connectionResolver = $db; } public function table(string $table): PresenceVerifierInterface { - $this->db = $this->db->table($table)->useWritePdo(); + $this->db = $this->connectionResolver->table($table)->useWritePdo(); return $this; } public function setConnection($connection) { - $this->db->connection($connection); + $this->connectionResolver->connection($connection); return $this; } -- Gitee