rikudou / json-rpc-bundle
使用现代 PHP 的 Symfony JSON-RPC 框架
Requires
- php: ^8.0
- symfony/framework-bundle: ^5.0
- symfony/yaml: ^5.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.1
- jetbrains/phpstorm-attributes: ^1.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^0.12.99
- phpstan/phpstan-symfony: ^0.12.44
This package is auto-updated.
Last update: 2024-08-29 06:01:18 UTC
README
这允许您使用现代 PHP 响应和处理 JSON-RPC 请求。
支持批量请求和单个请求。
安装
需要 PHP 8 和 Symfony 5.x。
composer require rikudou/json-rpc-bundle
用法
创建一个处理流量的控制器,该控制器非常简单,基本如下
<?php use Rikudou\JsonRpcBundle\Response\JsonRpcResponse; use Rikudou\JsonRpcBundle\Request\JsonRpcRequest; use Rikudou\JsonRpcBundle\Service\JsonRpcResponder; use Symfony\Component\Routing\Annotation\Route; final class MyController { #[Route('/jsonrpc')] public function myHandler(JsonRpcRequest $request, JsonRpcResponder $responder): JsonRpcResponse { return $responder->respond($request); } }
根据当前请求自动注入 JsonRpcRequest
对象,而 JsonRpcResponder
负责定位正确的方法并返回响应。
创建方法
创建方法非常简单,您有 3 种选择
- 在可调用对象(实现
__invoke()
)中使用Rikudou\JsonRpcBundle\Attribute\JsonRpcMethod
属性 - 实现
\Rikudou\JsonRpcBundle\JsonRpc\JsonRpcMethod
接口 - 手动注册可调用对象
请注意,虽然属性和接口具有相同的名称,但命名空间不同。
使用属性示例
<?php use Rikudou\JsonRpcBundle\Attribute\JsonRpcMethod; #[JsonRpcMethod('myMethodName')] final class MyMethod { public function __invoke(): string { return 'some-response'; } }
或者如果您想接受参数
<?php use Rikudou\JsonRpcBundle\Attribute\JsonRpcMethod; #[JsonRpcMethod('myMethodName')] final class MyMethod { public function __invoke(string $parameter1, string $parameter2): string { return $parameter1 . $parameter2; } }
如果提供了其他参数,可能会抛出异常,为了避免这种情况,您可以在参数中添加一个可变参数来捕获所有其他参数(参数的名称无关紧要)
<?php use Rikudou\JsonRpcBundle\Attribute\JsonRpcMethod; #[JsonRpcMethod('myMethodName')] final class MyMethod { public function __invoke(string $parameter1, string $parameter2, ...$allOtherParameters): string { return $parameter1 . $parameter2 . json_encode($allOtherParameters); } }
使用接口示例
<?php use Rikudou\JsonRpcBundle\JsonRpc\JsonRpcMethod; use Rikudou\JsonRpcBundle\Request\JsonRpcRequestParams; final class MyMethod implements JsonRpcMethod { public function getMethodName() : string { return 'myMethod'; } public function execute(JsonRpcRequestParams $params) : int|string|null|float|JsonSerializable|array|stdClass { return 'some-response'; } }
您还可以检查参数
<?php use Rikudou\JsonRpcBundle\JsonRpc\JsonRpcMethod; use Rikudou\JsonRpcBundle\Request\JsonRpcRequestParams; final class MyMethod implements JsonRpcMethod { public function getMethodName() : string { return 'myMethod'; } public function execute(JsonRpcRequestParams $params) : int|string|null|float|JsonSerializable|array|stdClass { if (!$params->hasParams()) { throw new RuntimeException('There are no parameters!'); } if (!isset($params['myParam'])) { throw new RuntimeException('The parameter "myParam" is missing!'); } $allParameters = $params->getParams(); return $params['myParam'] . json_encode($allParameters); } }
注册其他可调用对象
您可以在配置文件(例如 config/packages/json_rpc.yaml
)中手动注册其他可调用对象。
以下是一个配置示例
rikudou_json_rpc: callables: - name: myMethod callable: someGlobalFunction - name: myOtherMethod callable: App\MyClass::myStaticMethod - name: myThirdMethod callable: [App\MyClass, myStaticMethod] - name: myFourthMethod callable: ['@App\MyService', myInstanceMethod]
支持以下格式的可调用对象
- 函数
全局函数
- 静态方法
App\MyClass::someMethod
['App\MyClass', 'someMethod']
- 服务方法
['@App\MyService', 'someMethod']
请注意,服务名称以 @
开头。
与请求对象协同工作
如果您想在将请求对象传递给 JsonRpcResponder
服务之前对其进行检查,可以进行操作。
JsonRpcRequest
是一个标记接口,不包含任何方法,这意味着您需要自己检查它是否是 JsonRpcSingleRequest
或 JsonRpcBatchRequest
的实例。
JsonRpcSingleRequest
对象包含以下方法
getMethod(): string
getParams(): ?array
getId(): int|string|null
JsonRpcBatchRequest
包含以下方法
getRequests(): iterable<JsonRpcSingleRequest>
- 返回单个请求列表
在您的控制器中,您还可以为具体的类(JsonRpcSingleRequest
或 JsonRpcBatchRequest
)添加类型提示,但在那种情况下,当到达其他类型的请求时,您将收到一个 TypeError
。
如果您想在控制器类外部获取当前请求,您需要使用服务 JsonRpcRequestParser
<?php use Rikudou\JsonRpcBundle\Service\JsonRpcRequestParser; use Rikudou\JsonRpcBundle\Request\JsonRpcRequest; use Symfony\Component\HttpFoundation\RequestStack; final class MyService { public function __construct(private JsonRpcRequestParser $parser, private RequestStack $requestStack) { } public function getRequest(): JsonRpcRequest { // if you don't provide a Symfony\Component\HttpFoundation\Request parameter, the current request is used $request = $this->parser->parse(); // or you can specify the request yourself $request = $this->parser->parse($this->requestStack->getCurrentRequest()); return $this->parser->parse(); } }
与响应对象协同工作
如果您想在控制器中修改响应,可以调用 JsonRpcResponse
的 getJson()
方法,该方法返回一个数组,该数组包含将编码为 JSON 的原始数据。
您可以通过检查 JsonRpcSingleResponse
和 JsonRpcBatchResponse
的实例来检查响应是单个的还是批量的。
<?php use Symfony\Component\HttpFoundation\JsonResponse; use Rikudou\JsonRpcBundle\Request\JsonRpcRequest; use Rikudou\JsonRpcBundle\Service\JsonRpcResponder; use Symfony\Component\Routing\Annotation\Route; use Rikudou\JsonRpcBundle\Response\JsonRpcSingleResponse; use Rikudou\JsonRpcBundle\Response\JsonRpcBatchResponse; final class JsonRpcController { #[Route('/jsonrpc')] public function jsonRpc(JsonRpcRequest $request, JsonRpcResponder $responder): JsonResponse { $response = $responder->respond($request); $rawData = $response->getJson(); if ($response instanceof JsonRpcSingleResponse) { // do something with $rawData } elseif ($response instanceof JsonRpcBatchResponse) { // do something with $rawData } return new JsonResponse($rawData, $response->getStatusCode()); } }