rikudou/json-rpc-bundle

使用现代 PHP 的 Symfony JSON-RPC 框架

安装: 9

依赖者: 0

建议者: 0

安全性: 0

星星: 0

关注者: 2

分支: 0

开放问题: 0

类型:symfony-bundle

v1.1.1 2021-10-03 18:20 UTC

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 种选择

  1. 在可调用对象(实现 __invoke())中使用 Rikudou\JsonRpcBundle\Attribute\JsonRpcMethod 属性
  2. 实现 \Rikudou\JsonRpcBundle\JsonRpc\JsonRpcMethod 接口
  3. 手动注册可调用对象

请注意,虽然属性和接口具有相同的名称,但命名空间不同。

使用属性示例

<?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 是一个标记接口,不包含任何方法,这意味着您需要自己检查它是否是 JsonRpcSingleRequestJsonRpcBatchRequest 的实例。

JsonRpcSingleRequest 对象包含以下方法

  • getMethod(): string
  • getParams(): ?array
  • getId(): int|string|null

JsonRpcBatchRequest 包含以下方法

  • getRequests(): iterable<JsonRpcSingleRequest> - 返回单个请求列表

在您的控制器中,您还可以为具体的类(JsonRpcSingleRequestJsonRpcBatchRequest)添加类型提示,但在那种情况下,当到达其他类型的请求时,您将收到一个 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();
    }
}

与响应对象协同工作

如果您想在控制器中修改响应,可以调用 JsonRpcResponsegetJson() 方法,该方法返回一个数组,该数组包含将编码为 JSON 的原始数据。

您可以通过检查 JsonRpcSingleResponseJsonRpcBatchResponse 的实例来检查响应是单个的还是批量的。

<?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());
    }
}