plato-solutions / yii2-graphql
为 yii2 PHP 框架提供的 GraphQL 服务器端实现
Requires
- php: >=7.4.0
- ecodev/graphql-upload: ^6.1.0
- phpunit/php-code-coverage: 9.2.x-dev
- webonyx/graphql-php: ^14.6.2
- yiisoft/yii2: ^2.0.
- zendframework/zend-diactoros: ^2.1
Requires (Dev)
- phpunit/phpunit: ^9
This package is not auto-updated.
Last update: 2024-09-21 02:50:59 UTC
README
使用 GraphQL PHP 服务器实现。这是从 yii2-graphql 分支出来的,并扩展了 graphql-php 以适应 Yii2。
指南(适用于 Yii 基础模板)
与 Yii 高级模板相同,但
- 不是在
backend
命名空间中,而是在app
- 例如,命名空间应该是
namespace app\modules\graphql\...
- 例如,命名空间应该是
- 不是
main.php
,而是web.php
例如- 例如,配置在
config/web.php
- 例如,配置在
指南(适用于 Yii 高级模板)
安装
使用 composer
composer require Plato-solutions/yii2-graphql
启用 Yii JsonParser
在 backend/config/main.php
中启用对 JSON 请求的解析
'components' => [ 'request' => [ // ... other config 'parsers' => [ 'application/json' => 'yii\web\JsonParser', ] ] ]
创建一个 GraphQLModule
-
在您的基路径(即
backend
)中创建一个modules
文件夹 -
在模块文件夹中创建一个
graphql
文件夹。因此backend/modules/graphql
-
在该文件夹中创建一个
GraphqlModule.php
文件,内容如下:backend/modules/graphql/GraphqlModule.php
<?php namespace backend\modules\graphql; use yii\base\Module; use yii\graphql\GraphQLModuleTrait; class GraphqlModule extends Module{ use GraphQLModuleTrait; }
- 在
backend/config/main.php
中找到modules
配置并将其添加到其中,如下所示
'modules' => [ 'graphql => [ 'class' => 'backend\modules\graphql\GraphqlModule', ] ]
创建一个 控制器
- 在您的
modules/graphql
文件夹中创建一个controllers
文件夹。 - 在该文件夹中创建一个
DefaultController.php
文件,内容如下
<?php namespace backend\modules\graphql\controllers; use Yii; use yii\rest\Controller; class DefaultController extends Controller { public function actions() { Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; return [ 'index' => [ 'class' => 'yii\graphql\GraphQLAction' ], ]; } }
创建 GraphQL 类型
例如,在 backend/models
文件夹中的模型如下所示,
<?php /** * This is the model class for table "country". * * @property string $code * @property string $name * @property int $population * @property Person $leader */ class Country extends \yii\db\ActiveRecord {
其中 Person 是另一个模型,它有自己的属性,就像 Country
一样
- 在您的模块
modules/graphql
中创建一个文件夹,命名为types
。 - 创建一个
CountryType.php
(根据您的模型类命名,后缀为 Type),内容如下
<?php namespace backend\modules\graphql\types; use GraphQL\Type\Definition\Type; use yii\graphql\base\GraphQLType; use yii\graphql\GraphQL; class CountryType extends GraphQLType { protected $attributes = [ 'name' => 'country', 'description' => 'description here' ]; public function fields() { return [ 'id' => Type::id(), 'name' => Type::string(), 'population' => Type::int(), 'leader' => GraphQLType::type(PersonType::class) ]; } }
对所有 backend\models
中的模型执行上述操作。
有关类型下的所有类型完整列表,请参阅下方的标量类型。
为 模型 创建 GraphQL 查询
- 在您的模块
modules/graphql
中创建一个文件夹,命名为queries
。 - 创建一个
CountryQuery.php
(根据您的模型类命名,后缀为 Query),内容如下
<?php namespace backend\modules\graphql\queries; use GraphQL\Type\Definition\Type; use yii\graphql\queries\ModelQuery; use backend\modules\graphql\types\CountryType; use backend\models\Country; class CountryQuery extends ModelQuery { public $type = CountryType::class; public $model = Country::class; public function args() { return [ 'id' => Type::id(), 'name' => Type::string(), 'population' => Type::int(), 'leaderId' => Type::id() ]; // replace the non-scalar type with it's id in the args } }
为所有希望在查询中使用的 backend\models
中的模型执行上述操作。
设置 模式
- 在
backend/modules/graphql
中创建一个 PHP 文件schema.php
,内容如下
<?php return [ 'query' => [ 'country' => 'backend\modules\graphql\queries\CountryQuery', //... add all your queries here ], 'mutation' => [ //... add all your mutations here ], 'types' => [ 'country' => 'backend\modules\graphql\types\CountryType', //... add all your types here ] ];
- 在
backend/config/main.php
中有关modules
的部分中添加到schema.php
的路径,如下所示(确保schema
目录路径正确)。
'modules' => [ 'graphql' => [ 'class' => 'backend\modules\graphql\GraphqlModule', 'schema' => require __DIR__ . '/../../backend/modules/graphql/schema.php', ] ],
文档
类型
类型系统是GraphQL的核心,体现在GraphQLType
中。通过解构GraphQL协议并使用graph-php库来精细控制所有元素,可以方便地根据自身需求扩展类。
标量类型
GraphQL规范描述了几个内置的标量类型。在graphql-php中,它们作为类GraphQL\Type\Definition\Type的静态方法暴露。
GraphQLType
的主要元素
以下元素可以声明在类的$attributes
属性中,或作为方法,除非另有说明。这也适用于此之后的所有元素。
查询
GraphQLQuery
和GraphQLMutation
继承自GraphQLField
。元素结构一致,如果您想有一个可重用的Field
,可以继承它。每个Graphql
查询都需要对应一个GraphQLQuery
对象。ModelQuery
继承自GraphQLQuery
。
GraphQLField
的主要元素
突变
定义与GraphQLQuery
类似,请参见上文。
简化字段定义
简化了Field
的声明,不需要以类型键为数组的定义。
标准定义
//... 'id' => [ 'type' => Type::id(), ], //...
简化定义
//... 'id' => Type::id(), //...
输入验证
支持验证规则。除了基于graphql的验证外,还可以使用Yii Model验证,这目前用于输入参数的验证。将规则方法直接添加到突变定义中。
public function rules() { return [ ['password','boolean'] ]; }
授权验证
由于graphql查询可以组合,例如当查询合并两个查询时,这两个查询有不同的授权约束,需要自定义授权。我称此查询为“graphql操作”;当所有graphql操作条件配置完毕时,通过授权检查。
认证
在控制器的行为方法中,将授权方法设置为以下内容
function behaviors() { return [ 'authenticator'=>[ 'class' => 'yii\graphql\filter\auth\CompositeAuth', 'authMethods' => [ \yii\filters\auth\QueryParamAuth::class, ], 'except' => ['hello'] ], ]; }
如果想要支持IntrospectionQuery授权,相应的graphql操作是__schema
授权
如果用户已通过认证,您可能想检查对资源的访问权限。您可以在控制器中使用GraphqlAction
的checkAccess
方法。它将检查所有graphql操作。
class GraphqlController extends Controller { public function actions() { return [ 'index' => [ 'class' => 'yii\graphql\GraphQLAction', 'checkAccess'=> [$this,'checkAccess'], ] ]; } /** * authorization * @param $actionName * @throws yii\web\ForbiddenHttpException */ public function checkAccess($actionName) { $permissionName = $this->module->id . '/' . $actionName; $pass = Yii::$app->getAuthManager()->checkAccess(Yii::$app->user->id,$permissionName); if (!$pass){ throw new yii\web\ForbiddenHttpException('Access Denied'); } } }