Skip to content

Commit f98094f

Browse files
coding-linhengcodelinlimingxinleo
authored
Support method FormRequest::scene() which used to rewrite different rules according to different scenes. (#4002)
Co-authored-by: codelin <[email protected]> Co-authored-by: 李铭昕 <[email protected]>
1 parent f746675 commit f98094f

File tree

3 files changed

+123
-4
lines changed

3 files changed

+123
-4
lines changed

src/Request/FormRequest.php

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ class FormRequest extends Request implements ValidatesWhenResolved
4040
*/
4141
protected $errorBag = 'default';
4242

43+
/**
44+
* The scenes defined by developer.
45+
*
46+
* @var array
47+
*/
48+
protected $scenes = [];
49+
4350
/**
4451
* The input keys that should not be flashed on redirect.
4552
*
@@ -52,6 +59,20 @@ public function __construct(ContainerInterface $container)
5259
$this->setContainer($container);
5360
}
5461

62+
/**
63+
* @return $this
64+
*/
65+
public function scene(string $scene)
66+
{
67+
Context::set($this->getContextValidatorKey('scene'), $scene);
68+
return $this;
69+
}
70+
71+
public function getScene(): ?string
72+
{
73+
return Context::get($this->getContextValidatorKey('scene'));
74+
}
75+
5576
/**
5677
* Get the proper failed validation response for the request.
5778
*/
@@ -104,7 +125,7 @@ public function setContainer(ContainerInterface $container)
104125
*/
105126
protected function getValidatorInstance(): ValidatorInterface
106127
{
107-
return Context::getOrSet($this->getContextValidatorKey(), function () {
128+
return Context::getOrSet($this->getContextValidatorKey(ValidatorInterface::class), function () {
108129
$factory = $this->container->get(ValidationFactory::class);
109130

110131
if (method_exists($this, 'validator')) {
@@ -128,7 +149,7 @@ protected function createDefaultValidator(ValidationFactory $factory): Validator
128149
{
129150
return $factory->make(
130151
$this->validationData(),
131-
call_user_func_array([$this, 'rules'], []),
152+
$this->getRules(),
132153
$this->messages(),
133154
$this->attributes()
134155
);
@@ -183,8 +204,27 @@ protected function failedAuthorization()
183204
/**
184205
* Get context validator key.
185206
*/
186-
protected function getContextValidatorKey(): string
207+
protected function getContextValidatorKey(string $key): string
187208
{
188-
return sprintf('%s:%s', get_called_class(), ValidatorInterface::class);
209+
return sprintf('%s:%s', spl_object_hash($this), $key);
210+
}
211+
212+
/**
213+
* Get scene rules.
214+
*/
215+
protected function getRules()
216+
{
217+
$rules = call_user_func_array([$this, 'rules'], []);
218+
$scene = $this->getScene();
219+
if ($scene && isset($this->scenes[$scene]) && is_array($this->scenes[$scene])) {
220+
$newRules = [];
221+
foreach ($this->scenes[$scene] as $field) {
222+
if (array_key_exists($field, $rules)) {
223+
$newRules[$field] = $rules[$field];
224+
}
225+
}
226+
return $newRules;
227+
}
228+
return $rules;
189229
}
190230
}

tests/Cases/FormRequestTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@
1212
namespace HyperfTest\Validation\Cases;
1313

1414
use Hyperf\HttpMessage\Upload\UploadedFile;
15+
use Hyperf\Translation\ArrayLoader;
16+
use Hyperf\Translation\Translator;
1517
use Hyperf\Utils\Context;
18+
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
19+
use Hyperf\Validation\ValidationException;
20+
use Hyperf\Validation\ValidatorFactory;
1621
use HyperfTest\Validation\Cases\Stub\DemoRequest;
22+
use HyperfTest\Validation\Cases\Stub\FooSceneRequest;
1723
use Mockery;
1824
use PHPUnit\Framework\TestCase;
1925
use Psr\Container\ContainerInterface;
@@ -67,4 +73,42 @@ public function testRequestValidationDataWithSameKey()
6773

6874
$this->assertEquals(['file' => ['Invalid File.', $file]], $request->getValidationData());
6975
}
76+
77+
public function testSceneForFormRequest()
78+
{
79+
$psrRequest = Mockery::mock(ServerRequestInterface::class);
80+
$psrRequest->shouldReceive('getQueryParams')->andReturn([]);
81+
$psrRequest->shouldReceive('getUploadedFiles')->andReturn([]);
82+
$psrRequest->shouldReceive('getParsedBody')->andReturn([
83+
'mobile' => '12345',
84+
'name' => '',
85+
]);
86+
87+
Context::set(ServerRequestInterface::class, $psrRequest);
88+
$container = Mockery::mock(ContainerInterface::class);
89+
$translator = new Translator(new ArrayLoader(), 'en');
90+
$container->shouldReceive('get')->with(ValidatorFactoryInterface::class)->andReturn(new ValidatorFactory($translator));
91+
92+
$request = new FooSceneRequest($container);
93+
$res = $request->scene('info')->validated();
94+
$this->assertSame(['mobile' => '12345'], $res);
95+
96+
wait(function () use ($request, $psrRequest) {
97+
Context::set(ServerRequestInterface::class, $psrRequest);
98+
try {
99+
$request->validated();
100+
$this->assertTrue(false);
101+
} catch (\Throwable $exception) {
102+
$this->assertInstanceOf(ValidationException::class, $exception);
103+
}
104+
});
105+
106+
try {
107+
$request = new FooSceneRequest($container);
108+
$request->validated();
109+
$this->assertTrue(false);
110+
} catch (\Throwable $exception) {
111+
$this->assertInstanceOf(ValidationException::class, $exception);
112+
}
113+
}
70114
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* This file is part of Hyperf.
6+
*
7+
* @link https://www.hyperf.io
8+
* @document https://hyperf.wiki
9+
* @contact [email protected]
10+
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
11+
*/
12+
namespace HyperfTest\Validation\Cases\Stub;
13+
14+
use Hyperf\Validation\Request\FormRequest;
15+
16+
class FooSceneRequest extends FormRequest
17+
{
18+
public $scenes = [
19+
'save' => ['mobile', 'name'],
20+
'info' => ['mobile'],
21+
];
22+
23+
public function authorize(): bool
24+
{
25+
return true;
26+
}
27+
28+
public function rules(): array
29+
{
30+
return [
31+
'mobile' => 'required',
32+
'name' => 'required',
33+
];
34+
}
35+
}

0 commit comments

Comments
 (0)