moxuandi/yii2-graphql

facebook graphql server side for yii2 php framework

Installs: 77

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 0

Forks: 26

Type:yii2-extension

0.14.0 2020-11-09 09:50 UTC

This package is auto-updated.

Last update: 2024-11-09 19:09:52 UTC


README

使用 Facebook GraphQL 的PHP服务端实现. 扩展 graphql-php 以适用于 YII2.

Latest Stable Version Build Status Total Downloads

Englist document

yii-graphql特点

  • 配置简化,包括简化标准graphql协议的定义.
  • 按需要\懒加载,根据类型定义的全限定名,实现按需加载与懒,不需要在系统初始时将全部类型定义加载进入.
  • mutation输入验证支持
  • 提供控制器集成与授权支持

安装

使用 composer 安装:

composer require moxuandi/yii2-graphql

Type

类型系统是GraphQL的核心,体现在GraphQLType中,通过解构graphql协议,并利用graph-php库达到细粒度的对所有元素的控制,方便根据自身需要进行类扩展.

GraphQLType的主要元素,** 注意元素并不对应到属性或方法中(下同) **

Query

GraphQLQuery,GraphQLMutation继承了GraphQLField,元素结构是一致的,想做对于一些复用性的Field,可以继承它. Graphql的每次查询都需要对应到一个GraphQLQuery对象

GraphQLField的主要元素

Mutation

与GraphQLQuery是非常相像,参考说明.

简化处理

简化了Field的声明,字段可直接使用type

// 标准方式
'id' => [
    'type'=>type::id(),
],
// 简化写法
'id'=>type::id()

在YII使用

本组件采用trait的方式在Component组件中被引入,组件宿主建议的方式是Module

class Module extends \yii\base\Module {
    use GraphQLModuleTrait;
}

Yii config file:

'components' => [
    'graphql'=>[
       'class'=>'xxx\xxxx\module',
       //主graphql协议配置
       'schema' => [        
          'query' => [
              'user' => 'app\graphql\query\UsersQuery'
          ],
          'mutation' => [
              'login'
          ],
          //if you use sample query except query contain interface,fragment,not need set
          //the key must same as your class definded
          'types'=>[          
              'Story'=>'yiiunit\extensions\graphql\objects\types\StoryType'
          ],
        ]                
    ],    
];

采用的是actions的方法进行集成

class xxxController extends Controller{
   function actions()
   {
       return [
            'index'=>[
                'class'=>'yii\graphql\GraphQLAction'
            ]
       ];
   }
}

在采用动态解析的情况下,如果不想定义types时,schema的写法有讲究.可采用Type::class,避免采用Key方式,也方便直接通过IDE导航到对应的类下

'type' => GraphQL::type(UserType::class);

输入验证

针对mutation的数据提交,提供了验证支持. 除了graphql基于的验证外,还可以使用yii的验证,目前为针对输入参数验证.直接在mutation定义中增加rules方法, 与Yii Model的使用方式是一致的.

public function rules()
{
    return [
        ['password','boolean']
    ];
}

授权验证

由于graphql查询是可以采用组合方式,如一次查询合并了两个query,而这两个query具有不同的授权约束,因此在graph中需要采用自定义的验证方式。 我把这多次查询查询称为graphql actions;当所有的graphql actions条件都满足配置时,才通过授权检查。

授权

在controller的行为方法中设置采用的授权方法,例子如下,

function behaviors()
{
    return [
        'authenticator'=>[
            'class'=>'yii\graphql\filter\auth\CompositeAuth',
            'authMethods'=>[
                \yii\filters\auth\QueryParamAuth::class,
            ],
            'except'=>['hello']
        ],
    ];
}

如果要支持IntrospectionQueryr的授权,相应的graphql action为"__schema"

Demo

创建基于graphql协议的查询

每次查询对应一个GraphQLQuery文件,

use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;
use yii\graphql\base\GraphQLQuery;
use yii\graphql\GraphQL;

class UserQuery extends GraphQLQuery
{
    public function type()
    {
        return GraphQL::type(UserType::class);
    }

    public function args()
    {
        return [
            'id'=>[
                'type' => Type::nonNull(Type::id())
            ],
        ];
    }

    public function resolve($value, $args, $context, ResolveInfo $info)
    {
        return DataSource::findUser($args['id']);
    }


}

根据查询协议定义类型文件

use GraphQL\Type\Definition\Type;
use yii\graphql\base\GraphQLType;
use yii\graphql\GraphQL;

class UserType extends GraphQLType
{
    protected $attributes = [
        'name'=>'user',
        'description'=>'user is user'
    ];

    public function fields()
    {
        $result = [
            'id' => ['type'=>Type::id()],
            'email' => Types::email(),
            'email2' => Types::email(),
            'photo' => [
                'type' => GraphQL::type(ImageType::class),
                'description' => 'User photo URL',
                'args' => [
                    'size' => Type::nonNull(GraphQL::type(ImageSizeEnumType::class)),
                ]
            ],
            'firstName' => [
                'type' => Type::string(),
            ],
            'lastName' => [
                'type' => Type::string(),
            ],
            'lastStoryPosted' => GraphQL::type(StoryType::class),
            'fieldWithError' => [
                'type' => Type::string(),
                'resolve' => function() {
                    throw new \Exception("This is error field");
                }
            ]
        ];
        return $result;
    }

    public function resolvePhotoField(User $user,$args){
        return DataSource::getUserPhoto($user->id, $args['size']);
    }

    public function resolveIdField(User $user, $args)
    {
        return $user->id.'test';
    }

    public function resolveEmail2Field(User $user, $args)
    {
        return $user->email2.'test';
    }
}

查询实例

'hello' =>  "
        query hello{hello}
    ",

    'singleObject' =>  "
        query user {
            user(id:\"2\") {
                id
                email
                email2
                photo(size:ICON){
                    id
                    url
                }
                firstName
                lastName

            }
        }
    ",
    'multiObject' =>  "
        query multiObject {
            user(id: \"2\") {
                id
                email
                photo(size:ICON){
                    id
                    url
                }
            }
            stories(after: \"1\") {
                id
                author{
                    id
                }
                body
            }
        }
    ",
    'updateObject' =>  "
        mutation updateUserPwd{
            updateUserPwd(id: \"1001\", password: \"123456\") {
                id,
                username
            }
        }
    "

深入了解

有必要了解一些graphql-php的相关知识,这部分git上的文档相对还少些,需要对源码的阅读.下面列出重点

DocumentNode (语法解构)

array definitions
    array OperationDefinitionNode
        string kind
        array NameNode
            string kind
            string value

Future

  • ActiveRecord generate tool for generating query and mutation class.
  • 对于graphql的一些特殊语法,像参数语法,内置指令语法还未进行测试