Skip to content

Commit 19c1dc0

Browse files
committed
Merge branch 'master' into featrue/open-api
2 parents ae0dd8f + 4750ed6 commit 19c1dc0

27 files changed

Lines changed: 2100 additions & 19 deletions

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@ It allows you to map objects to arrays/JSON and **automatically generate OpenAPI
2424
- 🧬 **Auto-generate OpenAPI schema** using object definitions
2525
- ⚙️ Framework-agnostic — works with Laravel, Symfony, etc.
2626

27+
## Benchmark
28+
29+
```bash
30+
Run vendor/bin/phpbench run benchmarks/ --bootstrap=vendor/autoload.php
31+
PHPBench (1.4.1) running benchmarks... #standwithukraine
32+
with PHP version 8.4.8, xdebug ❌, opcache ❌
33+
34+
benchObjectCreation.....................I4 ✔ Mo117.841μs (±3.09%)
35+
benchObjectCreationWithoutCache.........I4 ✔ Mo284.568μs (±0.71%)
36+
benchObjectToArray......................I4 ✔ Mo62.883μs (±0.56%)
37+
benchObjectToArrayWithoutCache..........I4 ✔ Mo211.700μs (±0.84%)
38+
```
39+
2740
## Quick Start
2841

2942
### Installation

docs/benchmark.png

55.6 KB
Loading

docs/en/.gitbook.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
root: ./
2+
structure:
3+
readme: README.md
4+
summary: SUMMARY.md

docs/en/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# php-serialize
2+
3+
**php-serialize** is a powerful attribute-based PHP serialization library (requires PHP ≥ 8.1).
4+
It allows you to map objects to arrays or JSON, and can automatically generate OpenAPI documentation based on the same
5+
6+
> 🚀 Unified solution supporting API data serialization and document generation.
7+
8+
## ✨ Features
9+
10+
- 🏷️ Property alias mapping
11+
- 🔄 Automatic type conversion
12+
- 🔁 Support for deep object nesting
13+
- ❌ Support for skipping/excluding fields
14+
- 🧩 Recursive DTO (Data Transfer Object) serialization
15+
- 🧬 Automatically generate OpenAPI schema based on object definitions
16+
- ⚙️ Framework-agnostic — compatible with Laravel, Symfony, and more

docs/en/SUMMARY.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Summary
2+
3+
* [Introduction](README.md)
4+
* [Getting Started](getting-started.md)
5+
6+
## Attribute Conversion
7+
8+
* [Basic Type Mapping](mapper/base-mapper.md)
9+
* [Null Value Mapping](mapper/null-mapper.md)
10+
* [Enum Mapping](mapper/enum-mapper.md)
11+
* [Array Object Mapping](mapper/array-mapper.md)
12+
* [Union Type Mapping](mapper/union-mapper.md)
13+
14+
## Annotation Usage
15+
16+
* [Attribute Grouping](annotation/group-annotation.md)
17+
* [Input/Output Mapping](annotation/alisa-annotation.md)
18+
* [Mapper Mapping](annotation/mapper-annotation.md)
19+
* [Input/Output Ignoring](annotation/ignore-annotation.md)
20+
* [Date Format Mapping](annotation/date-annotation.md)
21+
* [Custom Annotation](annotation/customer-annotation.md)
22+
23+
## Parameter Mock Generation
24+
25+
* [Simple Value Faker](faker/value-faker.md)
26+
* [Collection Faker](faker/collection-faker.md)
27+
* [Nested Faker](faker/nested-faker.md)
28+
* [Method Faker](faker/method-faker.md)
29+
30+
## Automatic OpenAPI Documentation
31+
32+
* [Basic Demo](openapi/base-openapi.md)
33+
* [Parameter Annotations](openapi/annotation.md)
34+
* [Override Annotations](openapi/override-annotation.md)
35+
* [Configuration](openapi/config.md)
36+
* [Launch Service](openapi/launch.md)
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
## Name Mapping
2+
3+
### Basic Usage
4+
5+
```php
6+
use Astral\Serialize\Attributes\InputName;
7+
use Astral\Serialize\Attributes\OutputName;
8+
use Astral\Serialize\Serialize;
9+
10+
class User extends Serialize {
11+
// Use a different property name for input
12+
#[InputName('user_name')]
13+
public string $name;
14+
15+
// Use a different property name for output
16+
#[OutputName('user_id')]
17+
public int $id;
18+
19+
// Support different names for both input and output
20+
#[InputName('register_time')]
21+
#[OutputName('registeredAt')]
22+
public DateTime $createdAt;
23+
}
24+
25+
// Input data with different names
26+
$user = User::from([
27+
'user_name' => 'Job', // Mapped to $name
28+
'id' => 123, // Remains unchanged
29+
'register_time' => '2023-01-01 10:00:00' // Mapped to $createdAt
30+
]);
31+
32+
// Output data
33+
$userArray = $user->toArray();
34+
// $userArray toArray:
35+
// [
36+
// 'name' => 'Job',
37+
// 'user_id' => 123,
38+
// 'registeredAt' => '2023-01-01 10:00:00'
39+
// ]
40+
```
41+
42+
### Handling Multiple Input/Output Names
43+
44+
```php
45+
use Astral\Serialize\Attributes\InputName;
46+
use Astral\Serialize\Attributes\OutputName;
47+
use Astral\Serialize\Serialize;
48+
49+
class MultiOutputUser extends Serialize {
50+
// output multiple names
51+
#[OutputName('user_id')]
52+
#[OutputName('id')]
53+
#[OutputName('userId')]
54+
public int $id;
55+
56+
// Multiple input names, the first matching name in declaration order will be used
57+
#[InputName('user_name')]
58+
#[InputName('other_name')]
59+
#[InputName('userName')]
60+
public int $name;
61+
62+
}
63+
64+
// Scenario 1: Use the first matching input name
65+
$user1 = MultiInputUser::from([
66+
'user_name' => 'Job' // Use 'user_name'
67+
]);
68+
echo $user1->name; // Output 'Job'
69+
70+
// Scenario 2: Use the second matching input name
71+
$user2 = MultiInputUser::from([
72+
'other_name' => 'Tom' // Use 'Tom'
73+
]);
74+
echo $user2->name; // Output 'Tom'
75+
76+
// Scenario 3: Use the last input name
77+
$user3 = MultiInputUser::from([
78+
'userName' => 'Lin' // Use 'userName'
79+
]);
80+
echo $user3->name; // Output 'Lin'
81+
82+
// Scenario 4: When multiple are passed, the first matching name in declaration order is used
83+
$user4 = MultiInputUser::from([
84+
'userName' => 'Job',
85+
'other_name' => 'Tom',
86+
'user_name' => 'Lin',
87+
]);
88+
echo $user4->name; // Output 'Job'
89+
90+
// Create user object
91+
$user = MultiOutputUser::from([
92+
'id' => 123,
93+
'name' => 'Job'
94+
]);
95+
96+
// Convert to array
97+
// tips: Since id has multiple output names, the output includes ['user_id','id','userId']
98+
$userArray = $user->toArray();
99+
// $userArray toArray:
100+
// [
101+
// 'user_id' => 123,
102+
// 'id' => 123,
103+
// 'userId' => 123,
104+
// ]
105+
```
106+
107+
### Complex Mapping Scenarios
108+
109+
```php
110+
use Astral\Serialize\Serialize;
111+
112+
class ComplexUser extends Serialize {
113+
// Name mapping for nested objects
114+
#[InputName('user_profile')]
115+
public UserProfile $profile;
116+
117+
// Name mapping for array elements
118+
#[InputName('user_tags')]
119+
public array $tags;
120+
}
121+
122+
// Handle complex input structure
123+
$complexUser = ComplexUser::from([
124+
'user_profile' => [
125+
'nickname' => 'job',
126+
'age' => 25
127+
],
128+
'user_tags' => ['developer', 'programmer']
129+
]);
130+
131+
// Convert to standard array
132+
$complexUserArray = $complexUser->toArray();
133+
// $complexUserArray toArray:
134+
// [
135+
// 'profile' => UserProfile Object ([
136+
// 'nickname' => 'job',
137+
// 'age' => 25
138+
// ]),
139+
// 'tags' => ['developer', 'programmer']
140+
// ]
141+
```
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
### Custom Annotation Class Implementation
2+
3+
You can flexibly extend the input/output handling logic of the serialization library by defining custom annotation classes.
4+
5+
---
6+
7+
#### Input Processing Annotation Class
8+
9+
Implement the `InputValueCastInterface` interface, and override its `match` and `resolve` methods to customize the conversion and handling of input data.
10+
11+
- **`match`**: Used to determine whether to process the current value; returning `true` means `resolve` will be called.
12+
- **`resolve`**: Converts the matched input value and returns the result.
13+
14+
Example: Annotation class that adds a custom prefix to the input value
15+
16+
```php
17+
use Astral\Serialize\Contracts\Attribute\InputValueCastInterface;
18+
use Attribute;
19+
20+
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS)]
21+
class CustomerInput implements InputValueCastInterface
22+
{
23+
public function __construct(
24+
public string $prefix = '',
25+
) {
26+
}
27+
28+
public function match(mixed $value, DataCollection $collection, InputValueContext $context): bool
29+
{
30+
// Applies to all input values
31+
return true;
32+
}
33+
34+
public function resolve(mixed $value, DataCollection $collection, InputValueContext $context): mixed
35+
{
36+
// Add prefix to input value
37+
return $this->prefix . $value;
38+
}
39+
}
40+
```
41+
42+
### Output Processing Annotation Class
43+
44+
The output processing annotation is similar to the input processing annotation, but implements a different interface—`OutputValueCastInterface`, which is used to customize the conversion of serialized output values.
45+
46+
Example: Annotation class that adds a custom suffix to the serialized output value
47+
48+
```php
49+
use Astral\Serialize\Contracts\Attribute\OutputValueCastInterface;
50+
use Attribute;
51+
52+
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS)]
53+
class CustomerOutput implements OutputValueCastInterface
54+
{
55+
public function __construct(
56+
public string $suffix = '',
57+
) {
58+
}
59+
60+
public function match(mixed $value, DataCollection $collection, OutputValueContext $context): bool
61+
{
62+
// Applies to all output values
63+
return true;
64+
}
65+
66+
public function resolve(mixed $value, DataCollection $collection, OutputValueContext $context): mixed
67+
{
68+
// Add suffix to output value
69+
return $value . $this->suffix;
70+
}
71+
}
72+
```
73+
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
## Date/Time Conversion
2+
3+
1. Flexible Formatting
4+
Supports multiple input and output date/time formats
5+
Easily handles date representations from different regions
6+
2. Timezone Handling
7+
Supports conversion between different timezones
8+
Automatically handles timezone offsets for times
9+
3. Type Safety
10+
Automatically converts strings to DateTime objects
11+
Ensures type consistency and correctness
12+
13+
### Basic Usage
14+
15+
```php
16+
use Astral\Serialize\Attributes\Input\InputDateFormat;
17+
use Astral\Serialize\Attributes\Output\OutputDateFormat;
18+
use Astral\Serialize\Serialize;
19+
20+
class TimeExample extends Serialize {
21+
22+
// 输入时间格式转换
23+
#[InputDateFormat('Y-m-d')]
24+
public DateTime $dateTime;
25+
26+
// 输入时间格式转换
27+
#[InputDateFormat('Y-m-d')]
28+
public string $dateDateString;
29+
30+
// Output date format conversion
31+
#[OutputDateFormat('Y/m/d H:i')]
32+
public DateTime|string $processedAt;
33+
34+
35+
// Supports multiple date/time formats
36+
#[InputDateFormat('Y-m-d H:i:s')]
37+
#[OutputDateFormat('Y-m-d')]
38+
public string $createdAt;
39+
}
40+
41+
// Create order object
42+
$order = TimeExample::from([
43+
'dateTime' => new DateTime('2023-08-11'), // Input format: Y-m-d
44+
'dateDateString' => '2023-08-15', // Input format: Y-m-d
45+
'processedAt' => '2023-08-16 14:30', // Default input format, also supports DateTime objects
46+
'createdAt' => '2023-08-16 14:45:30' // Input format: Y-m-d H:i:s
47+
]);
48+
49+
// Convert to array
50+
$orderArray = $order->toArray();
51+
// Content of $orderArray:
52+
// [
53+
// 'dateTime' => '2023-08-11',
54+
// 'dateDateString' => '2023-08-15',
55+
// 'processedAt' => '2023/08/16 14:30',
56+
// 'createdAt' => '2023-08-16'
57+
// ]
58+
```
59+
60+
### Time Conversion with Timezone
61+
62+
```php
63+
64+
use Astral\Serialize\Attributes\Input\InputDateFormat;
65+
use Astral\Serialize\Attributes\Output\OutputDateFormat;
66+
use Astral\Serialize\Serialize;
67+
68+
class AdvancedTimeUser extends Serialize {
69+
// Supports timezone conversion
70+
#[InputDateFormat('Y-m-d H:i:s', timezone: 'UTC')]
71+
#[OutputDateFormat('Y-m-d H:i:s', timezone: 'Asia/Shanghai')]
72+
public DateTime $registeredAt;
73+
74+
// Supports date formats from different regions
75+
#[InputDateFormat('d/m/Y')] // UK format
76+
#[OutputDateFormat('Y-m-d')] // Standard format
77+
public DateTime $birthDate;
78+
}
79+
80+
// Use advanced time conversion
81+
$advancedUser = AdvancedTimeUser::from([
82+
'registeredAt' => '2023-08-16 10:00:00', // UTC time
83+
'birthDate' => '15/08/1990' // UK date format
84+
]);
85+
86+
$advancedUserArray = $advancedUser->toArray();
87+
// Content of $advancedUserArray:
88+
// [
89+
// 'registeredAt' => '2023-08-16 18:00:00', // Converted to Shanghai timezone
90+
// 'birthDate' => '1990-08-15'
91+
// ]
92+
```

0 commit comments

Comments
 (0)