mikle-heavy / yii2-json-rpc-2.0
为 Yii2 提供的 JSON RPC 2.0,用于请求和响应数据的严格类型验证
Requires
- php: >=5.4.0
- yiisoft/yii2: *
This package is not auto-updated.
Last update: 2024-09-29 02:33:11 UTC
README
cranetm/yii2-json-rpc-2.0 仓库克隆,略有修改
有什么区别
- 修复了已知的 Yii2 方法命名问题:API 方法必须按照 'do-some-things'(小写,用连字符分隔)的方式调用。现在您可以使用更舒适和熟悉的方式调用您的函数 - 'theCamelCase'。
- 修正了带有默认参数值的异常类代码
提示:如果您在调用 API 方法时遇到 404 错误,请设置 HTTP 头 "Content-Type: application/json",然后一切应该正常工作
以下所有文本均来自原始 Cranetm 仓库。
##JSON-RPC 2.0 for Yii2,支持请求和响应数据的严格类型验证
目录
验证功能
- 如果参数没有默认值,则对其执行验证
- 参数类型验证
2.1 将 DTO 作为结构化类型使用
2.2 使用方括号表示数组类型,如 string[]、int[]、bool[] 或 DTO:ClassName[] - @null 标签允许空值(默认情况下,所有数据都转换为特定类型)
- @inArray 标签限制值,如 @inArray["red"、"brown"、"yellow"]。仅适用于字符串和 int 数据类型。
使用方法
4 步即可轻松使用
-
通过 composer 安装
在 ./composer.json 中将以下内容添加到 'require' 部分
"mikle-heavy/yii2-json-rpc-2.0": "1.*"
然后在控制台/终端运行
composer update
-
在您的控制器中使用命名空间
use \JsonRpc2\Controller;
或者将扩展类更改为
class ServicesController extends \JsonRpc2\Controller { //BODY }
-
创建与 Yii 风格类似的操作
public function actionUpdate($message) { return ["message" => "hello ".$message]; }
-
向控制器发送 json 请求(使用 pretty urls,无需 index.php)
请求方法必须是 POST,Content-type 必须是 application/json
http://yoursite/services
带有数据
{ "jsonrpc": "2.0", "id": 1, "method": "update", "params": ["world"] }
响应将是
{"jsonrpc":"2.0","id":1,"result":{"message":"hello world"}}
认证扩展
如果您想使用 JSON RPC v2.0 认证扩展,您可以在 \JsonRpc2\Controller 实例中使用 \JsonRpc2\extensions\AuthTrait
class ServicesController extends \JsonRpc2\Controller { use \JsonRpc2\extensions\AuthTrait; }
然后,您可以使用认证令牌发出请求
{ "jsonrpc": "2.0", "id": 1, "method": "whoami", "auth": "some_access_token" }
最后,在 过滤器 或您的操作方法中,您可以调用 getAuthCredentials() 来获取请求对象的 "auth" 成员的值
public function actionWhoami($message) { $user = User::findIdentityByAccessToken($this->getAuthCredentials()); if (!$user) { throw new \JsonRpc2\extensions\AuthException('Missing auth', \JsonRpc2\extensions\AuthException::MISSING_AUTH); } return ['uid' => $user->id]; }
"auth" 值的性质以及您的 User 身份类如何使用它来查找IdentityByAccessToken是应用程序特定的。例如,在简单场景中,如果每个用户只有一个访问令牌,您可以将访问令牌存储在用户表的 access_token 列中。有关相关信息,请参阅 Yii 的 REST 认证 文档。
参数验证
为了验证参数数据,您必须为操作方法创建带有类型的 phpDoc @param 标签注释。
之后,参数数据将转换为文档中指定的类型。
示例 1
(从数组或对象解析参数并进行验证)在 JSON-RPC 参数中,方法参数可以以数组或对象的形式发送到服务器,其中键是参数名称,值是参数值。
例如,在 步骤4 中,我们以数组的形式发送参数,在这种情况下,数组的第一项是第一个方法参数,第二项是第二个参数,依此类推。
但我们可以以关联对象的形式接收参数,在这种情况下,参数的顺序不是必需的。
{ "jsonrpc": "2.0", "id": 1, "method": "update", "params": {"var1":"val1","var2":"val2","message":"world"} }
所有未使用的方法参数都将被忽略。
如果方法参数有默认值,则可以在请求中传递。如果缺少此参数,则将抛出 \JsonRpc2\Exception::INVALID_PARAMS。
示例 2
(简单类型,如字符串、整数、浮点数、布尔值)让我们将 $message 验证为 actionUpdate 中的整数并增加它。
/** * @param int $message * @return array */ public function actionUpdate($message) { return ["message" => ++$message]; }
对于后续请求
{"jsonrpc": "2.0","id": 1,"method": "update","params": [0.1]} {"jsonrpc": "2.0","id": 1,"method": "update","params": ["world"]} {"jsonrpc": "2.0","id": 1,"method": "update","params": [false]} {"jsonrpc": "2.0","id": 1,"method": "update","params": [{}]} //empty object {"jsonrpc": "2.0","id": 1,"method": "update","params": [[]]} //empty array
响应将是
{"jsonrpc":"2.0","id":1,"result":{"message":1}} //because all previous data converts as 0
但对于后续请求
{"jsonrpc": "2.0","id": 1,"method": "update","params": [1]} {"jsonrpc": "2.0","id": 1,"method": "update","params": ["1world"]} {"jsonrpc": "2.0","id": 1,"method": "update","params": [true]} {"jsonrpc": "2.0","id": 1,"method": "update","params": [["hello", "world"]]} {"jsonrpc": "2.0","id": 1,"method": "update","params": [{"hello": "world"}]}
响应将是
{"jsonrpc":"2.0","id":1,"result":{"message":2}} //because all previous data converts as 1
示例 3
(结构化类型,如数据传输对象 (DTO))如果方法中的参数数量太多,可以将它们全部放入一个对象中。
此对象应仅包含数据,因此使用 DTO 模式。
DTO 是一个具有描述类型(如 actionUpdate 中的 $message)的公共变量的类。
所有 DTO 类都必须继承自 \JsonRpc2\Dto,否则将抛出 \JsonRpc2\Exception::INTERNAL_ERROR。
DTO 变量必须具有 phpDoc @var 标记注释与类型。变量将转换为此类型,以及方法参数在 示例2 中。
DTO 变量的类型可以是另一个 DTO 类。
让我们创建一个包含一个字符串变量 $upper 的 Test DTO。
use \JsonRpc2\Dto; class Test extends Dto { /** @var string */ public $upper; }
...并更改 actionUpdate 以使用 Test DTO
/** * @param \JsonRpc2\Dto\Test $test * @return array */ public function actionUpdate($test) { return ["message" => strtoupper($test->upper)]; }
从现在开始,update 动作接受 $test 参数,将其转换为 Test 对象。因此,输入数据必须是对象,如下所示
{"jsonrpc": "2.0","id": 1,"method": "update","params": [{"upper": "hello world"}]} //or {"jsonrpc": "2.0","id": 1,"method": "update","params": {"test": {"upper": "hello world"}}}
并且 {"upper": "hello world"} 将被转换为具有变量验证的 \JsonRpc2\Test 对象。因此,响应将是
{"jsonrpc":"2.0","id":1,"result":{"message":"HELLO WORLD"}}
示例 4
(数组类型)为了更好的验证,'array' 作为变量或参数类型已被弃用,您必须使用带有简单类型或 DTO 的方括号。
您可以在动作或 DTO 中使用这些数组,并且所有参数数据都将递归验证。
‘Update’ 动作
/** * @param \JsonRpc2\Dto\Test[] $tests * @param string[] $messages * @return array */ public function actionUpdate($tests, $messages) { //BODY }
组合 DTO
use \JsonRpc2\Dto; class Combined extends Dto { /** @var string[] */ public $messages; /** @var \JsonRpc2\Dto\Test[] */ public $tests; }
响应数据验证
为了将来自服务器的不必要的数据类型转换为数据类型,您必须在服务器端验证数据。
为此,您必须在 PHPDoc 注释中添加带有数据类型的 @return 标记。
然后数据将被转换为指定的类型。
它与 @param 或 @var 验证相同。
以下示例中使用 DTO User
use JsonRpc2\Dto; class User extends Dto { /** @var int */ public $id; /** @var string */ public $name; /** @var string */ public $type = 'user'; /** @var string */ public $rights; }
示例 5
(响应验证):让我们创建一个名为 get-users 的动作,该动作模拟从存储中获取数据并返回 Users 数组
/** * @return \JsonRpc2\Dto\User[] */ public function actionGetUsers() { return [ [ "id" => "1", "name" => "Marco Polo", "type" => "admin", ], [ "id" => "234", "name" => "John Doe", "rights" => "settings" ] ]; }
响应数组中的每个元素都将转换为 User DTO
//request {"jsonrpc": "2.0","id": 1,"method": "get-users","params": []} //response {"jsonrpc":"2.0","id":1,"result":[{"id":1,"name":"Marco Polo","type":"admin","rights":""},{"id":234,"name":"John Doe","type":"user","rights":"settings"}]}
即使响应数组中缺少某些值,数据也将转换为 User 类型,具有 DTO 中描述的所有变量
空值和 @null 标签
默认情况下,不允许 null 类型,所有 null 值都将转换为特定类型
- 字符串 - ""
- 整数/浮点数 - 0
- 布尔值 - false
- DTO - 空对象(如果存在默认值,则使用)
- 数组 - []
但在许多情况下,您需要 null 值,并且需要添加标签 @null 在描述数据类型的下一行。
让我们更新 User 的权限变量以使其可空
/** * @var string * @null */ public $rights;
//request {"jsonrpc": "2.0","id": 1,"method": "get-users","params": []} //response {"jsonrpc":"2.0","id":1,"result":[{"id":1,"name":"Marco Polo","type":"admin","rights":null},{"id":234,"name":"John Doe","type":"user","rights":"settings"}]}
如我们所见,马可波罗的权限变量现在是 null。
值限制和 @inArray 标签
有许多情况,值可能限制为几个选项,并且应该验证它们的存在。
这是如何工作的?
让我们对变量User的权限进行限制并尝试发送请求。
/** * @var string * @inArray["dashboard","settings"] */ public $rights;
//request {"jsonrpc": "2.0","id": 1,"method": "get-users","params": []} //response {"jsonrpc":"2.0","id":1,"error":{"code":-32602,"message":"string value '' is not allowed. Allowed values is 'dashboard','settings'","data":null},"result":[]}
哎呀...出现了错误,Marcolpo和权限中的null值转换为字符串后变成了空字符串""。
但是存在没有空字符串的限制(["仪表板","设置")),所以我们出现了错误。
为了防止这种情况,您必须定义$rights的允许默认值,或者添加@null标签,或者更新限制(将""添加到inArray列表中),或者您可以定义Marcolpo的允许权限。
.... return [ [ "id" => "1", "name" => "Marco Polo", "type" => "admin", "rights" => "dashboard", ], ...
响应将是
{"jsonrpc":"2.0","id":1,"result":[{"id":1,"name":"Marco Polo","type":"admin","rights":"dashboard"},{"id":234,"name":"John Doe","type":"user","rights":"settings"}]}
CORS 支持
从1.2.5版本开始,扩展支持CORS请求。您可以将CORS过滤器附加到控制器上作为行为,只需遵循以下说明这里
#####如果您遇到功能问题,请不要害怕在这里注册。
#####感谢。