العمل مع JSON RPC في Symfony 4


مرحبًا بالجميع ، سنتحدث اليوم عن كيفية تكوين صداقات Symfony 4 و JSON RPC و OpenAPI 3.


هذه المقالة ليست مخصصة للمبتدئين ، يجب أن تفهم بالفعل كيفية التعامل مع Symfony و Depedency Injection وغيرها من الأشياء "المخيفة".


اليوم ، دعنا ننظر إلى تطبيق واحد محدد لـ JSON RPC.


تطبيق


هناك العديد من تطبيقات JSON RPC لـ Symfony ، على وجه الخصوص:



سنتحدث عن الأخير في هذا المقال. هذه المكتبة لديها العديد من المزايا التي حددت خياري.


تم تطويره دون ربط بأي إطار عمل ( yoanm / php-jsonrpc-server-sdk ) ، هناك حزمة لـ Symfony ، وله العديد من الحزم الإضافية التي تتيح لك إضافة فحص المدخلات والوثائق التلقائية والأحداث والواجهات لتكون قادرة على استكمال العمل دون إعادة تعريف.


تركيب


للبدء ، قم بتثبيت symfony / skeleton.


$ composer create-project symfony/skeleton jsonrpc 

انتقل إلى مجلد المشروع.


 $ cd jsonrpc 

وتثبيت المكتبة اللازمة.


 $ composer require yoanm/symfony-jsonrpc-http-server 

تخصيص.


 // config/bundles.php return [ ... Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Yoanm\SymfonyJsonRpcHttpServer\JsonRpcHttpServerBundle::class => ['all' => true], ... ]; 

 # config/routes.yaml json-rpc-endpoint: resource: '@JsonRpcHttpServerBundle/Resources/config/routing/endpoint.xml' 

 # config/packages/json_rpc.yaml json_rpc_http_server: ~ 

إضافة خدمة من شأنها تخزين جميع أساليبنا.


 // src/MappingCollector.php <?php namespace App; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodAwareInterface; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; class MappingCollector implements JsonRpcMethodAwareInterface { /** @var JsonRpcMethodInterface[] */ private $mappingList = []; public function addJsonRpcMethod(string $methodName, JsonRpcMethodInterface $method): void { $this->mappingList[$methodName] = $method; } /** * @return JsonRpcMethodInterface[] */ public function getMappingList() : array { return $this->mappingList; } } 

وأضف الخدمة إلى services.yaml.


 # config/services.yaml services: ... mapping_aware_service: class: App\MappingCollector tags: ['json_rpc_http_server.method_aware'] ... 

طريقة التنفيذ


تتم إضافة أساليب RPC JSON كخدمات عادية في ملف services.yaml. ننفذ أولاً طريقة ping نفسها.


 // src/Method/PingMethod.php <?php namespace App\Method; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; class PingMethod implements JsonRpcMethodInterface { public function apply(array $paramList = null) { return 'pong'; } } 

وأضف كخدمة.


 # config/services.yaml services: ... App\Method\PingMethod: public: false tags: [{ method: 'ping', name: 'json_rpc_http_server.jsonrpc_method' }] ... 

نطلق خادم الويب المدمج في Symfony.


 $ symfony serve 

نحن نحاول إجراء مكالمة.


 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{ "jsonrpc":"2.0","method":"ping","params":[],"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "result": "pong" } ] 

الآن نطبق الطريقة التي تستقبل المعلمات. سنعود بيانات الإدخال كإجابة.


 // src/Method/ParamsMethod.php <?php namespace App\Method; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; class ParamsMethod implements JsonRpcMethodInterface { public function apply(array $paramList = null) { return $paramList; } } 

 # config/services.yaml services: ... App\Method\ParamsMethod: public: false tags: [{ method: 'params', name: 'json_rpc_http_server.jsonrpc_method' }] ... 

محاولة الاتصال.


 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{ "jsonrpc":"2.0","method":"params","params":{"name":"John","age":21},"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "result": { "name": "John", "age": 21 } } ] 

التحقق من صحة طريقة الإدخال


إذا كان التحقق التلقائي من البيانات عند إدخال الطريقة مطلوبًا ، فهناك في هذه الحالة أداة التحقق من حزمة yoanm / symfony-jsonrpc-params-validator .


 $ composer require yoanm/symfony-jsonrpc-params-validator 

ربط الحزمة.


 // config/bundles.php return [ ... Yoanm\SymfonyJsonRpcParamsValidator\JsonRpcParamsValidatorBundle::class => ['all' => true], ... ]; 

يجب أن تقوم الطرق التي تحتاج إلى التحقق من الإدخال بتطبيق الواجهة Yoanm \ JsonRpcParamsSymfonyValidator \ Domain \ MethodWithValidatedParamsInterface . دعونا تعديل فئة ParamsMethod قليلا .


 // src/Method/ParamsMethod.php <?php namespace App\Method; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Optional; use Symfony\Component\Validator\Constraints\Positive; use Symfony\Component\Validator\Constraints\Required; use Yoanm\JsonRpcParamsSymfonyValidator\Domain\MethodWithValidatedParamsInterface; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; class ParamsMethod implements JsonRpcMethodInterface, MethodWithValidatedParamsInterface { public function apply(array $paramList = null) { return $paramList; } public function getParamsConstraint() : Constraint { return new Collection(['fields' => [ 'name' => new Required([ new Length(['min' => 1, 'max' => 32]) ]), 'age' => new Required([ new Positive() ]), 'sex' => new Optional([ new Choice(['f', 'm']) ]), ]]); } } 

الآن إذا قمنا بتنفيذ الطلب مع معلمات فارغة أو مع أخطاء ، سوف نتلقى الأخطاء المقابلة في الرد.


 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{"jsonrpc":"2.0","method":"params","params":[],"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "error": { "code": -32602, "message": "Invalid params", "data": { "violations": [ { "path": "[name]", "message": "This field is missing.", "code": "2fa2158c-2a7f-484b-98aa-975522539ff8" }, { "path": "[age]", "message": "This field is missing.", "code": "2fa2158c-2a7f-484b-98aa-975522539ff8" } ] } } } ] 

 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{"jsonrpc":"2.0","method":"params","params":{"name":"John","age":-1},"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "error": { "code": -32602, "message": "Invalid params", "data": { "violations": [ { "path": "[age]", "message": "This value should be positive.", "code": "778b7ae0-84d3-481a-9dec-35fdb64b1d78" } ] } } } 

 $ curl 'http://127.0.0.1:8000/json-rpc' --data-binary '[{ "jsonrpc":"2.0","method":"params","params":{"name":"John","age":21,"sex":"u"},"id" : 1 }]' 

 [ { "jsonrpc": "2.0", "id": 1, "error": { "code": -32602, "message": "Invalid params", "data": { "violations": [ { "path": "[sex]", "message": "The value you selected is not a valid choice.", "code": "8e179f1b-97aa-4560-a02f-2a8b42e49df7" } ] } } } ] 

وثائق السيارات


تثبيت حزمة إضافية.


 composer require yoanm/symfony-jsonrpc-http-server-doc 

نحن تكوين الحزمة.


 // config/bundles.php return [ ... Yoanm\SymfonyJsonRpcHttpServerDoc\JsonRpcHttpServerDocBundle::class => ['all' => true], ... ]; 

 # config/routes.yaml ... json-rpc-endpoint-doc: resource: '@JsonRpcHttpServerDocBundle/Resources/config/routing/endpoint.xml' 

 # config/packages/json_rpc.yaml ... json_rpc_http_server_doc: ~ 

يمكنك الآن الحصول على الوثائق بتنسيق JSON.


 $ curl 'http://127.0.0.1:8000/doc' 

الجواب
 { "methods": [ { "identifier": "Params", "name": "params" }, { "identifier": "Ping", "name": "ping" } ], "errors": [ { "id": "ParseError-32700", "title": "Parse error", "type": "object", "properties": { "code": -32700 } }, { "id": "InvalidRequest-32600", "title": "Invalid request", "type": "object", "properties": { "code": -32600 } }, { "id": "MethodNotFound-32601", "title": "Method not found", "type": "object", "properties": { "code": -32601 } }, { "id": "ParamsValidationsError-32602", "title": "Params validations error", "type": "object", "properties": { "code": -32602, "data": { "type": "object", "nullable": true, "required": true, "siblings": { "violations": { "type": "array", "nullable": true, "required": false } } } } }, { "id": "InternalError-32603", "title": "Internal error", "type": "object", "properties": { "code": -32603, "data": { "type": "object", "nullable": true, "required": false, "siblings": { "previous": { "description": "Previous error message", "type": "string", "nullable": true, "required": false } } } } } ], "http": { "host": "127.0.0.1:8000" } } 

لكن كيف ذلك؟ وأين هو وصف المعلمات الإدخال؟ للقيام بذلك ، ضع حزمة أخرى yoanm / symfony-jsonrpc-params-sf-restrictions-doc .


 $ composer require yoanm/symfony-jsonrpc-params-sf-constraints-doc 

 // config/bundles.php return [ ... Yoanm\SymfonyJsonRpcParamsSfConstraintsDoc\JsonRpcParamsSfConstraintsDocBundle::class => ['all' => true], ... ]; 

الآن إذا قدمنا ​​طلبًا ، فسنحصل على أساليب JSON مع معلمات بالفعل.


 $ curl 'http://127.0.0.1:8000/doc' 

الجواب
 { "methods": [ { "identifier": "Params", "name": "params", "params": { "type": "object", "nullable": false, "required": true, "siblings": { "name": { "type": "string", "nullable": true, "required": true, "minLength": 1, "maxLength": 32 }, "age": { "type": "string", "nullable": true, "required": true }, "sex": { "type": "string", "nullable": true, "required": false, "allowedValues": [ "f", "m" ] } } } }, { "identifier": "Ping", "name": "ping" } ], "errors": [ { "id": "ParseError-32700", "title": "Parse error", "type": "object", "properties": { "code": -32700 } }, { "id": "InvalidRequest-32600", "title": "Invalid request", "type": "object", "properties": { "code": -32600 } }, { "id": "MethodNotFound-32601", "title": "Method not found", "type": "object", "properties": { "code": -32601 } }, { "id": "ParamsValidationsError-32602", "title": "Params validations error", "type": "object", "properties": { "code": -32602, "data": { "type": "object", "nullable": true, "required": true, "siblings": { "violations": { "type": "array", "nullable": true, "required": false, "item_validation": { "type": "object", "nullable": true, "required": true, "siblings": { "path": { "type": "string", "nullable": true, "required": true, "example": "[key]" }, "message": { "type": "string", "nullable": true, "required": true }, "code": { "type": "string", "nullable": true, "required": false } } } } } } } }, { "id": "InternalError-32603", "title": "Internal error", "type": "object", "properties": { "code": -32603, "data": { "type": "object", "nullable": true, "required": false, "siblings": { "previous": { "description": "Previous error message", "type": "string", "nullable": true, "required": false } } } } } ], "http": { "host": "127.0.0.1:8000" } } 

أوبنابي 3


لكي تكون وثائق JSON متوافقة مع معيار OpenAPI 3 ، تحتاج إلى تثبيت yoanm / symfony-jsonrpc-http-server-openapi-doc .


 $ composer require yoanm/symfony-jsonrpc-http-server-openapi-doc 

تخصيص.


 // config/bundles.php return [ ... Yoanm\SymfonyJsonRpcHttpServerOpenAPIDoc\JsonRpcHttpServerOpenAPIDocBundle::class => ['all' => true], ... ]; 

بعد تقديم طلب جديد ، سنتلقى وثائق JSON بتنسيق OpenApi 3.


 $ curl 'http://127.0.0.1:8000/doc/openapi.json' 

الجواب
 { "openapi": "3.0.0", "servers": [ { "url": "http:\/\/127.0.0.1:8000" } ], "paths": { "\/Params\/..\/json-rpc": { "post": { "summary": "\"params\" json-rpc method", "operationId": "Params", "requestBody": { "required": true, "content": { "application\/json": { "schema": { "allOf": [ { "type": "object", "required": [ "jsonrpc", "method" ], "properties": { "id": { "example": "req_id", "oneOf": [ { "type": "string" }, { "type": "number" } ] }, "jsonrpc": { "type": "string", "example": "2.0" }, "method": { "type": "string" }, "params": { "title": "Method parameters" } } }, { "type": "object", "required": [ "params" ], "properties": { "params": { "$ref": "#\/components\/schemas\/Method-Params-RequestParams" } } }, { "type": "object", "properties": { "method": { "example": "params" } } } ] } } } }, "responses": { "200": { "description": "JSON-RPC response", "content": { "application\/json": { "schema": { "allOf": [ { "type": "object", "required": [ "jsonrpc" ], "properties": { "id": { "example": "req_id", "oneOf": [ { "type": "string" }, { "type": "number" } ] }, "jsonrpc": { "type": "string", "example": "2.0" }, "result": { "title": "Result" }, "error": { "title": "Error" } } }, { "type": "object", "properties": { "result": { "description": "Method result" } } }, { "type": "object", "properties": { "error": { "oneOf": [ { "$ref": "#\/components\/schemas\/ServerError-ParseError-32700" }, { "$ref": "#\/components\/schemas\/ServerError-InvalidRequest-32600" }, { "$ref": "#\/components\/schemas\/ServerError-MethodNotFound-32601" }, { "$ref": "#\/components\/schemas\/ServerError-ParamsValidationsError-32602" }, { "$ref": "#\/components\/schemas\/ServerError-InternalError-32603" } ] } } } ] } } } } } } }, "\/Ping\/..\/json-rpc": { "post": { "summary": "\"ping\" json-rpc method", "operationId": "Ping", "requestBody": { "required": true, "content": { "application\/json": { "schema": { "allOf": [ { "type": "object", "required": [ "jsonrpc", "method" ], "properties": { "id": { "example": "req_id", "oneOf": [ { "type": "string" }, { "type": "number" } ] }, "jsonrpc": { "type": "string", "example": "2.0" }, "method": { "type": "string" }, "params": { "title": "Method parameters" } } }, { "type": "object", "properties": { "method": { "example": "ping" } } } ] } } } }, "responses": { "200": { "description": "JSON-RPC response", "content": { "application\/json": { "schema": { "allOf": [ { "type": "object", "required": [ "jsonrpc" ], "properties": { "id": { "example": "req_id", "oneOf": [ { "type": "string" }, { "type": "number" } ] }, "jsonrpc": { "type": "string", "example": "2.0" }, "result": { "title": "Result" }, "error": { "title": "Error" } } }, { "type": "object", "properties": { "result": { "description": "Method result" } } }, { "type": "object", "properties": { "error": { "oneOf": [ { "$ref": "#\/components\/schemas\/ServerError-ParseError-32700" }, { "$ref": "#\/components\/schemas\/ServerError-InvalidRequest-32600" }, { "$ref": "#\/components\/schemas\/ServerError-MethodNotFound-32601" }, { "$ref": "#\/components\/schemas\/ServerError-ParamsValidationsError-32602" }, { "$ref": "#\/components\/schemas\/ServerError-InternalError-32603" } ] } } } ] } } } } } } } }, "components": { "schemas": { "Method-Params-RequestParams": { "type": "object", "nullable": false, "required": [ "name", "age" ], "properties": { "name": { "type": "string", "nullable": true, "minLength": 1, "maxLength": 32 }, "age": { "type": "string", "nullable": true }, "sex": { "type": "string", "nullable": true, "enum": [ "f", "m" ] } } }, "ServerError-ParseError-32700": { "title": "Parse error", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": -32700 } } } ] }, "ServerError-InvalidRequest-32600": { "title": "Invalid request", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": -32600 } } } ] }, "ServerError-MethodNotFound-32601": { "title": "Method not found", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": -32601 } } } ] }, "ServerError-ParamsValidationsError-32602": { "title": "Params validations error", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code", "data" ], "properties": { "code": { "example": -32602 }, "data": { "type": "object", "nullable": true, "properties": { "violations": { "type": "array", "nullable": true, "items": { "type": "object", "nullable": true, "required": [ "path", "message" ], "properties": { "path": { "type": "string", "nullable": true, "example": "[key]" }, "message": { "type": "string", "nullable": true }, "code": { "type": "string", "nullable": true } } } } } } } } ] }, "ServerError-InternalError-32603": { "title": "Internal error", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": -32603 }, "data": { "type": "object", "nullable": true, "properties": { "previous": { "description": "Previous error message", "type": "string", "nullable": true } } } } } ] } } } } 

وثائق الاستجابة للطريقة


لا توجد وظائف منتظمة (على سبيل المثال ، عن طريق تطبيق واجهة) تسمح لك بإضافة استجابات الطريقة إلى الوثائق. ولكن هناك فرصة ، من خلال الاشتراك في الأحداث ، لإضافة المعلومات الضرورية بنفسك.


أضف مستمع.


 # config/services.yaml services: ... App\Listener\MethodDocListener: tags: - name: 'kernel.event_listener' event: 'json_rpc_http_server_doc.method_doc_created' method: 'enhanceMethodDoc' - name: 'kernel.event_listener' event: 'json_rpc_http_server_openapi_doc.array_created' method: 'enhanceDoc' ... 

 // src/Listener/MethodDocListener.php <?php namespace App\Listener; use App\Domain\JsonRpcMethodWithDocInterface; use Yoanm\JsonRpcServerDoc\Domain\Model\ErrorDoc; use Yoanm\SymfonyJsonRpcHttpServerDoc\Event\MethodDocCreatedEvent; use Yoanm\SymfonyJsonRpcHttpServerOpenAPIDoc\Event\OpenAPIDocCreatedEvent; class MethodDocListener { public function enhanceMethodDoc(MethodDocCreatedEvent $event) : void { $method = $event->getMethod(); if ($method instanceof JsonRpcMethodWithDocInterface) { $doc = $event->getDoc(); $doc->setResultDoc($method->getDocResponse()); foreach ($method->getDocErrors() as $error) { if ($error instanceof ErrorDoc) { $doc->addCustomError($error); } } $doc->setDescription($method->getDocDescription()); $doc->addTag($method->getDocTag()); } } public function enhanceDoc(OpenAPIDocCreatedEvent $event) { $doc = $event->getOpenAPIDoc(); $doc['info'] = [ 'title' => 'Main title', 'version' => '1.0.0', 'description' => 'Main description' ]; $event->setOpenAPIDoc($doc); } } 

أيضًا ، حتى لا يتم وصف وثائق الطرق مباشرةً في المستمع ، سنقوم بإنشاء واجهة يجب أن تطبقها الطرق نفسها.


 // src/Domain/JsonRpcMethodWithDocInterface.php <?php namespace App\Domain; use Yoanm\JsonRpcServerDoc\Domain\Model\ErrorDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\TypeDoc; interface JsonRpcMethodWithDocInterface { /** * @return TypeDoc */ public function getDocResponse(): TypeDoc; /** * @return ErrorDoc[] */ public function getDocErrors(): array; /** * @return string */ public function getDocDescription(): string; /** * @return string */ public function getDocTag(): string; } 

أضف الآن طريقة جديدة تحتوي على المعلومات اللازمة.


 // src/Method/UserMethod.php <?php namespace App\Method; use App\Domain\JsonRpcMethodWithDocInterface; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\Choice; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Optional; use Symfony\Component\Validator\Constraints\Positive; use Symfony\Component\Validator\Constraints\Required; use Yoanm\JsonRpcParamsSymfonyValidator\Domain\MethodWithValidatedParamsInterface; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; use Yoanm\JsonRpcServerDoc\Domain\Model\ErrorDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ArrayDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\NumberDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\ObjectDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\StringDoc; use Yoanm\JsonRpcServerDoc\Domain\Model\Type\TypeDoc; class UserMethod implements JsonRpcMethodInterface, MethodWithValidatedParamsInterface, JsonRpcMethodWithDocInterface { public function apply(array $paramList = null) { return [ 'name' => $paramList['name'], 'age' => $paramList['age'], 'sex' => $paramList['sex'] ?? null, ]; } public function getParamsConstraint() : Constraint { return new Collection(['fields' => [ 'name' => new Required([ new Length(['min' => 1, 'max' => 32]) ]), 'age' => new Required([ new Positive() ]), 'sex' => new Optional([ new Choice(['f', 'm']) ]), ]]); } public function getDocDescription(): string { return 'User method'; } public function getDocTag(): string { return 'main'; } public function getDocErrors(): array { return [new ErrorDoc('Error 1', 1)]; } public function getDocResponse(): TypeDoc { $response = new ObjectDoc(); $response->setNullable(false); $response->addSibling((new StringDoc()) ->setNullable(false) ->setDescription('Name of user') ->setName('name') ); $response->addSibling((new NumberDoc()) ->setNullable(false) ->setDescription('Age of user') ->setName('age') ); $response->addSibling((new StringDoc()) ->setNullable(true) ->setDescription('Sex of user') ->setName('sex') ); return $response; } } 

لا تنس تسجيل خدمة جديدة.


 services: ... App\Method\UserMethod: public: false tags: [{ method: 'user', name: 'json_rpc_http_server.jsonrpc_method' }] ... 

الآن ، مع تقديم طلب جديد إلى / doc/openapi.json ، نحصل على بيانات جديدة.


 curl 'http://127.0.0.1:8000/doc/openapi.json' 

الجواب
 { "openapi": "3.0.0", "servers": [ { "url": "http:\/\/127.0.0.1:8000" } ], "paths": { ... "\/User\/..\/json-rpc": { "post": { "summary": "\"user\" json-rpc method", "description": "User method", "tags": [ "main" ], ... "responses": { "200": { "description": "JSON-RPC response", "content": { "application\/json": { "schema": { "allOf": [ ... { "type": "object", "properties": { "result": { "$ref": "#\/components\/schemas\/Method-User-Result" } } }, { "type": "object", "properties": { "error": { "oneOf": [ { "$ref": "#\/components\/schemas\/Error-Error11" }, ... ] } } } ] } } } } } } } }, "components": { "schemas": { ... "Method-User-Result": { "type": "object", "nullable": false, "properties": { "name": { "description": "Name of user", "type": "string", "nullable": false }, "age": { "description": "Age of user", "type": "number", "nullable": false }, "sex": { "description": "Sex of user", "type": "string", "nullable": true } } }, "Error-Error11": { "title": "Error 1", "allOf": [ { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "number" }, "message": { "type": "string" } } }, { "type": "object", "required": [ "code" ], "properties": { "code": { "example": 1 } } } ] }, ... } }, "info": { "title": "Main title", "version": "1.0.0", "description": "Main description" } } 

تصور وثائق JSON


JSON رائع ، لكن الناس عادة ما يرغبون في رؤية نتيجة أكثر إنسانية. يمكن تقديم ملف /doc/openapi.json لخدمات التصور الخارجية ، مثل Swagger Editor .



إذا رغبت في ذلك ، يمكنك تثبيت Swagger UI في مشروعنا. سوف نستخدم حزمة harmbandstra / swagger-ui- package.


للنشر الصحيح للموارد ، نضيف ما يلي مع composer.json.


  "scripts": { "auto-scripts": { "cache:clear": "symfony-cmd", "assets:install %PUBLIC_DIR%": "symfony-cmd" }, "post-install-cmd": [ "HarmBandstra\\SwaggerUiBundle\\Composer\\ScriptHandler::linkAssets", "@auto-scripts" ], "post-update-cmd": [ "HarmBandstra\\SwaggerUiBundle\\Composer\\ScriptHandler::linkAssets", "@auto-scripts" ] }, 

بعد أن وضعنا الحزمة.


 $ composer require harmbandstra/swagger-ui-bundle 

ربط الحزمة.


 // config/bundles.php <?php return [ // ... HarmBandstra\SwaggerUiBundle\HBSwaggerUiBundle::class => ['dev' => true] ]; 

 # config/routes.yaml _swagger-ui: resource: '@HBSwaggerUiBundle/Resources/config/routing.yml' prefix: /docs 

 # config/packages/hb_swagger_ui.yaml hb_swagger_ui: directory: "http://127.0.0.1:8000" files: - "/doc/openapi.json" 

الآن ، وبعد الرابط http://127.0.0.1:8000/docs/ ، نحصل على الوثائق في شكل جميل.



النتائج


نتيجة لجميع عمليات التلاعب ، حصلنا على JSON RPC تعمل على أساس Symfony 4 والوثائق التلقائية لـ OpenAPI مع التصور باستخدام Swagger UI.


شكرا لكم جميعا

Source: https://habr.com/ru/post/ar457750/


All Articles