Skip to content

Commit a7c97a1

Browse files
authored
Featrue/normalizers (#10)
* add validate * add validation docs
1 parent d32e138 commit a7c97a1

File tree

14 files changed

+236
-18
lines changed

14 files changed

+236
-18
lines changed

benchmarks/SerializeBench.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function setupObject(): void
8383
Revs(500),
8484
Iterations(5),
8585
BeforeMethods([ 'setupObjectCreation']),
86-
Assert('mode(variant.time.avg) < 120 microseconds +/- 5%')
86+
Assert('mode(variant.time.avg) < 130 microseconds +/- 5%')
8787
]
8888
public function benchObjectCreation(): void
8989
{

docs/en/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* [Array Object Mapping](mapper/array-mapper.md)
1212
* [Union Type Mapping](mapper/union-mapper.md)
1313
* [Output Format](mapper/out.md)
14+
* [Validation](mapper/validate.md)
1415

1516
## Annotation Usage
1617

docs/en/mapper/out.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ $user = User::from([
2727
### Outputting the Object
2828

2929
```php
30+
3031
// $user is an object by default
3132
echo $user->name; // Output: Jon
3233
echo $user->age; // Output: 30

docs/en/mapper/validate.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
## Parameter Validation
2+
3+
### Validation via the `validate` Method
4+
5+
The `Serialize` class provides a `validate` method that is automatically called when an object is created using the `from` method. You can implement custom data validation logic within this method.
6+
7+
Here's an example:
8+
9+
```php
10+
use Astral\Serialize\Serialize;
11+
12+
class TestConstructValidationFromSerialize extends Serialize
13+
{
14+
public string $type_string;
15+
16+
/**
17+
* Data validation method
18+
* Automatically called after object creation via the from method
19+
*/
20+
public function validate(): void
21+
{
22+
// Validate the value of the type_string property
23+
if ($this->type_string !== '123') {
24+
throw new Exception('type_string must be equal to 123');
25+
}
26+
27+
// You can also modify property values
28+
$this->type_string = '234';
29+
}
30+
}
31+
```
32+
33+
### Validation in `__construct`
34+
35+
When creating objects directly using the `__construct` method, you can implement parameter validation logic in the constructor. However, note that this approach can only access properties defined in the constructor and cannot access other properties.
36+
37+
```php
38+
use Astral\Serialize\Serialize;
39+
40+
class TestConstructFromSerialize extends Serialize
41+
{
42+
// Note: This property cannot be accessed in the constructor
43+
// If you need to validate this property, use the validate method
44+
public string $not_validate_string;
45+
46+
/**
47+
* Parameter validation in the constructor
48+
* @param string $type_string The input string parameter
49+
*/
50+
public function __construct(
51+
public string $type_string,
52+
) {
53+
// Validate the input parameter
54+
if ($this->type_string !== '123') {
55+
throw new Exception('type_string must be equal to 123');
56+
}
57+
58+
// Modify the property value
59+
$this->type_string = '234';
60+
}
61+
}

docs/zh/SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
* [数组对象转换](mapper/array-mapper.md)
1212
* [联合类型转换](mapper/union-mapper.md)
1313
* [输出格式](mapper/out.md)
14+
* [参数校验](mapper/validate.md)
15+
1416

1517
## 注解类使用
1618

docs/zh/mapper/validate.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
## 参数校验
2+
3+
### 使用 validate 方法进行参数校验
4+
5+
`Serialize` 类提供了一个 `validate` 方法,当通过 `from` 方法创建对象时,该方法会被自动调用。我们可以在 `validate` 方法中实现自定义的数据验证逻辑。
6+
7+
下面是一个使用示例:
8+
9+
```php
10+
use Astral\Serialize\Serialize;
11+
12+
class TestConstructValidationFromSerialize extends Serialize
13+
{
14+
public string $type_string;
15+
16+
/**
17+
* 数据验证方法
18+
* 在对象通过 from 方法创建后自动调用
19+
*/
20+
public function validate(): void
21+
{
22+
// 验证 type_string 属性的值
23+
if ($this->type_string !== '123') {
24+
throw new Exception('type_string 必须等于 123');
25+
}
26+
27+
// 可以修改属性值
28+
$this->type_string = '234';
29+
}
30+
}
31+
```
32+
33+
### 在构造函数中进行参数校验
34+
35+
当直接使用 `__construct` 方法创建对象时,可以在构造函数中实现参数验证逻辑。但需要注意的是,这种方式只能访问构造函数中定义的属性,无法访问其他属性。
36+
37+
```php
38+
use Astral\Serialize\Serialize;
39+
40+
class TestConstructFromSerialize extends Serialize
41+
{
42+
// 注意:这个属性在构造函数中无法访问
43+
// 如果需要验证此属性,请使用 validate 方法
44+
public string $not_validate_string;
45+
46+
/**
47+
* 构造函数中的参数验证
48+
* @param string $type_string 输入的字符串参数
49+
*/
50+
public function __construct(
51+
public string $type_string,
52+
) {
53+
// 验证传入的参数
54+
if ($this->type_string !== '123') {
55+
throw new Exception('type_string 必须等于 123');
56+
}
57+
58+
// 修改属性值
59+
$this->type_string = '234';
60+
}
61+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Astral\Serialize\Casts\InputValue;
6+
7+
use Astral\Serialize\Contracts\Attribute\InputValueCastInterface;
8+
use Astral\Serialize\Enums\TypeKindEnum;
9+
use Astral\Serialize\Support\Collections\DataCollection;
10+
use Astral\Serialize\Support\Context\InputValueContext;
11+
12+
class InputValueOnlyBaseTypeCast implements InputValueCastInterface
13+
{
14+
public function match(mixed $value, DataCollection $collection, InputValueContext $context): bool
15+
{
16+
return $value !== null && $collection->isNullable() === false && count($collection->getTypes()) == 1 ;
17+
}
18+
19+
public function resolve(mixed $value, DataCollection $collection, InputValueContext $context): mixed
20+
{
21+
return match ($collection->getTypes()[0]->kind) {
22+
TypeKindEnum::INT => (int)$value,
23+
TypeKindEnum::FLOAT => (float)$value,
24+
TypeKindEnum::STRING => (string)$value,
25+
TypeKindEnum::BOOLEAN => (bool)$value,
26+
default => $value,
27+
};
28+
}
29+
}

src/Resolvers/InputResolver.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public function __construct(
2626
/**
2727
* @throws ReflectionException
2828
*/
29-
public function resolve(ChooseSerializeContext $chooseContext, GroupDataCollection $groupCollection, array $payload)
29+
public function resolve(ChooseSerializeContext $chooseContext, GroupDataCollection $groupCollection, array $payload): object
3030
{
3131
$reflectionClass = $this->reflectionClassInstanceManager->get($groupCollection->getClassName());
3232
$object = $reflectionClass->newInstanceWithoutConstructor();
@@ -72,6 +72,11 @@ classInstance: $object,
7272
$this->inputConstructCast->resolve($groupCollection->getConstructProperties(), $object, $constructInputs);
7373
}
7474

75+
// validate execution
76+
if(method_exists($object,'validate')){
77+
$object->validate();
78+
}
79+
7580
return $object;
7681

7782
}

src/Serialize.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ public function setContext(SerializeContext $context): static
3232

3333
public static function setGroups(array|string $groups): SerializeContext
3434
{
35-
/** @var SerializeContext<static> $serializeContext */
3635
$serializeContext = ContextFactory::build(static::class);
3736
return $serializeContext->setGroups((array)$groups);
3837
}
@@ -84,6 +83,11 @@ public static function faker(): static
8483
return $instance;
8584
}
8685

86+
public function validate(): void
87+
{
88+
89+
}
90+
8791
public function __debugInfo()
8892
{
8993
$res = get_object_vars($this);

src/Support/Config/ConfigManager.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Astral\Serialize\Casts\InputValue\InputObjectBestMatchChildCast;
88
use Astral\Serialize\Casts\InputValue\InputValueEnumCast;
99
use Astral\Serialize\Casts\InputValue\InputValueNullCast;
10+
use Astral\Serialize\Casts\InputValue\InputValueOnlyBaseTypeCast;
1011
use Astral\Serialize\Casts\Normalizer\ArrayNormalizerCast;
1112
use Astral\Serialize\Casts\Normalizer\DateTimeNormalizerCast;
1213
use Astral\Serialize\Casts\Normalizer\JsonNormalizerCast;
@@ -36,6 +37,7 @@ class ConfigManager
3637
InputArraySingleChildCast::class,
3738
InputArrayBestMatchChildCast::class,
3839
InputValueEnumCast::class,
40+
InputValueOnlyBaseTypeCast::class,
3941
];
4042

4143
/** @var (OutValueCastInterface|string)[] $outputValueCasts */

0 commit comments

Comments
 (0)