diff --git a/.openapi.php b/.openapi.php index 4d47fa7..302fb95 100644 --- a/.openapi.php +++ b/.openapi.php @@ -49,4 +49,16 @@ * You can override or extend this list in your config file. */ 'exclude_dirs' => [], + + /** + * Response Data Structure Definition + * + * Defines the basic structure of API responses, including status code, return message, and data body + * + */ + 'response' => [ + 'code' => ['description' =>'状态码', 'example'=> 200], + 'message' => ['description' =>'返回信息', 'example'=> '操作成功'], + 'data' => 'T', + ] ]; diff --git a/docs/en/openapi/config.md b/docs/en/openapi/config.md index a63d465..c5f2b94 100644 --- a/docs/en/openapi/config.md +++ b/docs/en/openapi/config.md @@ -60,5 +60,17 @@ return [ * */ 'exclude_dirs' => [], + + /** + * Response Data Structure Definition + * + * Defines the basic structure of API responses, including status code, return message, and data body + * + */ + 'response' => [ + 'code' => ['description' =>'状态码', 'example'=> 200], + 'message' => ['description' =>'返回信息', 'example'=> '操作成功'], + 'data' => 'T', + ] ]; ``` \ No newline at end of file diff --git a/docs/zh/openapi/base-openapi.md b/docs/zh/openapi/base-openapi.md index 002566d..dbba8b4 100644 --- a/docs/zh/openapi/base-openapi.md +++ b/docs/zh/openapi/base-openapi.md @@ -59,4 +59,18 @@ docker run -v $PWD/vendor/astral/php-serialize/src/OpenApi/Frankenphp/Caddyfile ``` 访问 `http://127.0.0.1:8089/docs` 查看文档 +![UI-IMG](./ui.png) + +### Docker启动 + +先进入项目根目录 + +```shell +docker run -v $PWD/vendor/astral/php-serialize/src/OpenApi/Frankenphp/Caddyfile:/etc/frankenphp/Caddyfile -v $PWD:/app -p 8089:80 dunglas/frankenphp +``` + +访问 `http://127.0.0.1:8089` 展示OpenApi JSON文档 + +访问 `http://127.0.0.1:8089/docs` 展示UI文档 + ![UI-IMG](./ui.png) \ No newline at end of file diff --git a/docs/zh/openapi/config.md b/docs/zh/openapi/config.md index 207cc43..68a099c 100644 --- a/docs/zh/openapi/config.md +++ b/docs/zh/openapi/config.md @@ -60,5 +60,17 @@ return [ * */ 'exclude_dirs' => [], + + /** + * 响应数据结构定义 + * + * 定义API响应的基本结构,包含状态码、返回信息和数据主体 + * + */ + 'response' => [ + 'code' => ['description' =>'状态码', 'example'=> 200], + 'message' => ['description' =>'返回信息', 'example'=> '操作成功'], + 'data' => 'T', + ] ]; ``` \ No newline at end of file diff --git a/src/OpenApi/Collections/OpenApiCollection.php b/src/OpenApi/Collections/OpenApiCollection.php index 5b71d9a..33dc041 100644 --- a/src/OpenApi/Collections/OpenApiCollection.php +++ b/src/OpenApi/Collections/OpenApiCollection.php @@ -12,6 +12,7 @@ use Astral\Serialize\OpenApi\Annotations\Tag; use Astral\Serialize\OpenApi\Enum\ContentTypeEnum; use Astral\Serialize\OpenApi\Enum\ParameterTypeEnum; +use Astral\Serialize\OpenApi\Handler\Config; use Astral\Serialize\OpenApi\Storage\OpenAPI\Method\Method; use Astral\Serialize\OpenApi\Storage\OpenAPI\RequestBodyStorage; use Astral\Serialize\OpenApi\Storage\OpenAPI\ResponseStorage; @@ -121,11 +122,17 @@ public function buildResponse(string $className,array $groups = []): ResponseSto { $responseStorage = new ResponseStorage(); + $baseResponse = Config::get('response',[]); + if ($className) { $schemaStorage = (new SchemaStorage())->build($this->buildResponseParameterCollections($className,$groups)); $responseStorage->withParameter($schemaStorage); } + if($baseResponse){ + $responseStorage->addGlobParameters($baseResponse); + } + return $responseStorage; } diff --git a/src/OpenApi/Storage/OpenAPI/ResponseStorage.php b/src/OpenApi/Storage/OpenAPI/ResponseStorage.php index db870b8..10126c9 100755 --- a/src/OpenApi/Storage/OpenAPI/ResponseStorage.php +++ b/src/OpenApi/Storage/OpenAPI/ResponseStorage.php @@ -23,6 +23,32 @@ public function withParameter(SchemaStorage $schema): static return $this; } + public function addGlobParameters(array $vols): void + { + $dates = $this->parameter['properties'] ?? []; + $required = $this->parameter['required'] ?? []; + + $this->parameter['properties'] = []; + + foreach ($vols as $field => $item){ + if($item === 'T'){ + $this->parameter['properties'][$field] = [ + 'type' => 'object', + 'properties' => $dates, + 'required' => $required, + ]; + }else{ + $this->parameter['properties'][$field] = [ + 'type' => 'string', + 'description' => $item['description'] ?? '', + 'example' => $item['example'], + ]; + } + + } + + } + public function getData(): array { return [ diff --git a/src/Serialize.php b/src/Serialize.php index 5e016bb..04faf3b 100644 --- a/src/Serialize.php +++ b/src/Serialize.php @@ -2,10 +2,12 @@ namespace Astral\Serialize; +use Astral\Serialize\OpenApi\Handler\Config; use Astral\Serialize\Support\Context\SerializeContext; use Astral\Serialize\Support\Factories\ContextFactory; +use JsonSerializable; -abstract class Serialize +abstract class Serialize implements JsonSerializable { private ?SerializeContext $_context = null; @@ -71,4 +73,22 @@ public function __debugInfo() return $res; } + + public function jsonSerialize(): array + { + $baseResponse = Config::get('response',[]); + if($baseResponse){ + $resultData = []; + foreach ($baseResponse as $field => $item){ + if($item === 'T'){ + $resultData[$field] = $this->toArray(); + }else{ + $resultData[$field] = $item['example'] ?? ''; + } + } + return $resultData; + } + + return $this->toArray(); + } } diff --git a/tests/Openapi/BaseGroupOpenApiTest.php b/tests/Openapi/BaseGroupOpenApiTest.php index 071ed01..e83f48e 100644 --- a/tests/Openapi/BaseGroupOpenApiTest.php +++ b/tests/Openapi/BaseGroupOpenApiTest.php @@ -78,7 +78,7 @@ public function one(TestBaseGroupRequest $request): void expect($schema['properties'])->toHaveCount(3)->toHaveKeys(['input_change_group_1_33_2_11', 'input_group_2_22', 'input_group_2_33']); - $schema = $post->responses[200]['content']['application/json']['schema']; + $schema = $post->responses[200]['content']['application/json']['schema']['properties']['data']; expect($schema['properties'])->toHaveCount(3)->toHaveKeys(['out_group_1_11', 'out_group_1_22', 'out_group_1_33_2_11']); }); diff --git a/tests/Openapi/EnumOpenApiTest.php b/tests/Openapi/EnumOpenApiTest.php index f14002e..ff8660e 100644 --- a/tests/Openapi/EnumOpenApiTest.php +++ b/tests/Openapi/EnumOpenApiTest.php @@ -59,7 +59,9 @@ public function one(OpenapiEnumRequest $request): void $requestBody = $post->requestBody; $schema = $requestBody['content']['application/json']['schema']; - expect($schema['properties']) + + expect($schema)->toHaveKey('properties') + ->and($schema['properties']) ->toHaveKeys([ 'test_enum', 'test_string_enum', @@ -67,24 +69,24 @@ public function one(OpenapiEnumRequest $request): void 'test_one_of_enum', ]) ->and($schema['properties']['test_enum'])->toMatchArray([ - 'type' => 'string', + 'type' => 'string', 'description' => 'optional values:ENUM_1、ENUM_2', - 'example' => '', + 'example' => '', ]) ->and($schema['properties']['test_string_enum'])->toMatchArray([ - 'type' => 'string', + 'type' => 'string', 'description' => 'optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4', - 'example' => '', + 'example' => '', ]) ->and($schema['properties']['test_string_2_enum'])->toMatchArray([ - 'type' => 'string', + 'type' => 'string', 'description' => 'optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4', - 'example' => '', + 'example' => '', ]) ->and($schema['properties']['test_one_of_enum'])->toMatchArray([ - 'type' => 'oneOf', + 'type' => 'oneOf', 'description' => 'optional values:ENUM_1、ENUM_2、ENUM_3、ENUM_4', - 'example' => '', + 'example' => '', ]) ->and($schema['properties']['test_one_of_enum']['oneOf'])->toBeArray()->toHaveCount(2) ->and($schema['properties']['test_one_of_enum']['oneOf'][0])->toMatchArray(['type' => 'string']) diff --git a/tests/Openapi/OpenApiTest.php b/tests/Openapi/OpenApiTest.php index 288453e..70f491a 100644 --- a/tests/Openapi/OpenApiTest.php +++ b/tests/Openapi/OpenApiTest.php @@ -93,9 +93,10 @@ public function one(TestOpenApiRequest $request): TestOpenApiResponse $response200 = $post->responses[200]; expect($response200['description'])->toBe('成功'); - $schema = $response200['content']['application/json']['schema']; - expect($schema['properties'])->toHaveKeys(['name', 'id']) - ->and($schema['required'])->toHaveCount(1) - ->and($schema['required'][0])->toBeString('id'); + $data = $response200['content']['application/json']['schema']['properties']['data']; + + expect($data['properties'])->toHaveKeys(['name', 'id']) + ->and($data['required'])->toHaveCount(1) + ->and($data['required'][0])->toBeString('id'); });