magdv / yii2-graphql
graphql server side for yii2 php framework
Installs: 465
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 26
Type:yii2-extension
Requires
- php: ^8.0
- ecodev/graphql-upload: ^6.1
- laminas/laminas-diactoros: ^3.2
- webonyx/graphql-php: ^14.11
- yiisoft/yii2: ^2.0.47
Requires (Dev)
- overtrue/phplint: ^9.0
- phpunit/phpunit: ^9
- rector/rector: ^1.0
- squizlabs/php_codesniffer: ^3.9
- vimeo/psalm: 5.23.1
This package is auto-updated.
Last update: 2024-11-18 10:23:08 UTC
README
Using GraphQL PHP server implementation. A fork of yii2-graphql which extends graphql-php to apply to Yii2.
Guide (For Yii Basic Template)
Same as for Yii Advanced Template, but
- instead of the
backend
namespace, it'sapp
- eg the namespace should be
namespace app\modules\graphql\...
- eg the namespace should be
- Instead of
main.php
, it'sweb.php
eg `- eg the config is in
config/web.php
- eg the config is in
Guide (For Yii Advanced Template)
Install
Using composer
composer require Plato-solutions/yii2-graphql
Enable Yii JsonParser
To enable parsing for JSON requests in backend/config/main.php
'components' => [ 'request' => [ // ... other config 'parsers' => [ 'application/json' => 'yii\web\JsonParser', ] ] ]
Create a GraphQLModule
-
Create a folder
modules
in your base path (iebackend
) -
Create a
graphql
folder in the modules folder. Thusbackend/modules/graphql
-
Create a
GraphqlModule.php
file in there with the following content:backend/modules/graphql/GraphqlModule.php
<?php namespace backend\modules\graphql; use yii\base\Module; use yii\graphql\GraphQLModuleTrait; class GraphqlModule extends Module{ use GraphQLModuleTrait; }
- In
backend/config/main.php
find themodules
config and add to it so it looks like this:
'modules' => [ 'graphql => [ 'class' => 'backend\modules\graphql\GraphqlModule', ] ]
Create a Controller
- In your
modules/graphql
folder create acontrollers
folder. - Create a
DefaultController.php
file in there with the following content:
<?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' ], ]; } }
Create GraphQL Types
For a model in folder backend/models
like the example below,
<?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 {
where Person is another Model with it's own attributes just like the Country
- Create a folder in your module
modules/graphql/
and name ittypes
. - Create a
CountryType.php
(name it after your model class, suffix with Type) the following content
<?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) ]; } }
Do the above for all the models in backend\models
.
For a full list of the types available under Type, see Scalar Types below.
Create GraphQL Queries for Models
- Create a folder in your module
modules/graphql/
and name itqueries
. - Create a
CountryQuery.php
(name it after your model class, suffix with Query) the following content
<?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 } }
Do the above for all the models in backend\models
you want to have queries for.
Set Up Schema
- In
backend/modules/graphql/
create a php fileschema.php
with the content:
<?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 ] ];
- In
backend/config/main.php
in the part aboutmodules
add a path to theschema.php
as follows (make sure the directory path toschema
is right).
'modules' => [ 'graphql' => [ 'class' => 'backend\modules\graphql\GraphqlModule', 'schema' => require __DIR__ . '/../../backend/modules/graphql/schema.php', ] ],
Docs
Type
The type system is the core of GraphQL, which is embodied in GraphQLType
. By deconstructing the GraphQL protocol and using the graph-php library to achieve fine-grained control of all elements, it is convenient to extend the class according to its own needs
Scalar Types
The GraphQL specification describes several built-in scalar types. In graphql-php they are exposed as static methods of the class GraphQL\Type\Definition\Type:
The main elements of GraphQLType
The following elements can be declared in the $attributes
property of the class, or as a method, unless stated otherwise. This also applies to all elements after this.
Query
GraphQLQuery
and GraphQLMutation
inherit GraphQLField
. The element structure is consistent, and if you would like a reusable Field
, you can inherit it.
Each query of Graphql
needs to correspond to a GraphQLQuery
object. ModelQuery
inherits from GraphQLQuery
.
The main elements of GraphQLField
Mutation
Definition is similar to GraphQLQuery
, please refer to the above.
Simplified Field Definition
Simplifies the declarations of Field
, removing the need to defined as an array with the type key.
Standard Definition
//... 'id' => [ 'type' => Type::id(), ], //...
Simplified Definition
//... 'id' => Type::id(), //...
Input validation
Validation rules are supported. In addition to graphql based validation, you can also use Yii Model validation, which is currently used for the validation of input parameters. The rules method is added directly to the mutation definition.
public function rules() { return [ ['password','boolean'] ]; }
Authorization verification
Since graphql queries can be combined, such as when a query merges two query, and the two query have different authorization constraints, custom authentication is required. I refer to this query as "graphql actions"; when all graphql actions conditions are configured, it passes the authorization check.
Authenticate
In the behavior method of controller, the authorization method is set as follows
function behaviors() { return [ 'authenticator'=>[ 'class' => 'yii\graphql\filter\auth\CompositeAuth', 'authMethods' => [ \yii\filters\auth\QueryParamAuth::class, ], 'except' => ['hello'] ], ]; }
If you want to support IntrospectionQuery authorization, the corresponding graphql action is __schema
Authorization
If the user has passed authentication, you may want to check the access for the resource. You can use GraphqlAction
's checkAccess
method
in the controller. It will check all graphql actions.
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'); } } }