api-skeletons/doctrine-graphql

此软件包已被废弃,不再维护。作者建议使用api-skeletons/doctrine-orm-graphql软件包。

Doctrine ORM 的 GraphQL 类型驱动程序

8.1.3 2023-10-15 10:14 UTC

README

该项目已被弃用,转而使用API-Skeletons/doctrine-orm-graphql

如果您是 8.x 分支的用户,请参阅升级指南

所有原始文档如下。

Build Status Code Coverage Scrutinizer Code Quality PHP Version Total Downloads License

此库为 Doctrine ORM 提供了一个框架无关的 GraphQL 驱动程序,用于与webonyx/graphql-php一起使用。配置从零到详尽都有。支持多个驱动程序的多重配置。

详细的文档可在这里找到。

有关示例应用程序,请访问https://graphql.lcdb.org/

库亮点

安装

运行以下命令使用Composer安装此库

composer require api-skeletons/doctrine-graphql

实体关系图

此实体关系图,由Skipper创建,用于下面的查询示例和测试此库。

Entity Relationship Diagram

快速入门

将属性添加到您的 Doctrine 实体中

use ApiSkeletons\Doctrine\GraphQL\Attribute as GraphQL;

#[GraphQL\Entity]
class Artist 
{
    #[GraphQL\Field]
    public $id;
    
    #[GraphQL\Field]
    public $name;
    
    #[GraphQL\Association]
    public $performances;
}

#[GraphQL\Entity]
class Performance
{
    #[GraphQL\Field]
    public $id;
    
    #[GraphQL\Field]
    public $venue;
    
    /**
     * Not all fields need attributes.
     * Only add attribues to fields you want available in GraphQL
     */
    public $city;
}

创建驱动程序和 GraphQL 模式

use ApiSkeletons\Doctrine\GraphQL\Driver;
use Doctrine\ORM\EntityManager;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Schema;

$driver = new Driver($entityManager);

$schema = new Schema([
    'query' => new ObjectType([
        'name' => 'query',
        'fields' => [
            'artists' => [
                'type' => $driver->connection($driver->type(Artist::class)),
                'args' => [
                    'filter' => $driver->filter(Artist::class),
                    'pagination' => $driver->pagination(),
                ],
                'resolve' => $driver->resolve(Artist::class),
            ],
        ],
    ]),
    'mutation' => new ObjectType([
        'name' => 'mutation',
        'fields' => [
            'artistUpdateName' => [
                'type' => $driver->type(Artist::class),
                'args' => [
                    'id' => Type::nonNull(Type::id()),
                    'input' => Type::nonNull($driver->input(Artist::class, ['name'])),
                ],
                'resolve' => function ($root, $args) use ($driver): Artist {
                    $artist = $driver->get(EntityManager::class)
                        ->getRepository(Artist::class)
                        ->find($args['id']);

                    $artist->setName($args['input']['name']);
                    $driver->get(EntityManager::class)->flush();

                    return $artist;
                },
            ],
        ],
    ]),
]);

运行 GraphQL 查询

use GraphQL\GraphQL;

$query = '{ 
    artists { 
        edges { 
            node { 
                id 
                name 
                performances { 
                    edges { 
                        node { 
                            venue 
                        } 
                    } 
                } 
            } 
        } 
    }
}';

$result = GraphQL::executeQuery(
    schema: $schema,
    source: $query,
    variableValues: null,
    operationName: null
);

$output = $result->toArray();

运行 GraphQL 变更

use GraphQL\GraphQL;

$query = 'mutation ArtistUpdateName($id: Int!, $name: String!) {
    artistUpdateName(id: $id, input: { name: $name }) {
        id
        name
    }
}';

$result = GraphQL::executeQuery(
    schema: $schema,
    source: $query,
    variableValues: ['id' => 1, 'name' => 'newName'],
    operationName: 'ArtistUpdateName'
);

$output = $result->toArray();

筛选

对于每个属性字段和每个属性关联,您的 GraphQL 查询中都有筛选器。

示例

{
  artists ( filter: { name: { contains: "dead" } } ) {
    edges {
      node {
        id
        name
        performances ( filter: { venue: { eq: "The Fillmore" } } ) {
          edges { 
            node {
              venue
            }
          }
        }
      }
    }
  }
}

每个字段都有自己的筛选器集合。大多数字段都有以下筛选器

  • eq - 等于。
  • neq - 不等于。
  • lt - 小于。
  • lte - 小于或等于。
  • gt - 大于。
  • gte - 大于或等于。
  • isnull - 为空。如果值为 true,则字段必须为空。如果值为 false,则字段不能为空。
  • between - 介于。等同于在同一个字段上使用 gte 和 lte。提供值作为 low, high
  • in - 存在于以逗号分隔的值列表中。
  • notin - 不存在于以逗号分隔的值列表中。
  • startwith - 一个带有值右侧通配符的 like 查询。
  • endswith - 在值左侧带有通配符的类似查询。
  • contains - 一个类似查询。

事件

过滤查询构建器

您可以通过订阅事件来修改用于解决任何连接的查询构建器。每个连接可能具有一个独特的事件名称。Entity::class . '.filterQueryBuilder'被推荐使用。将其作为$driver->resolve()的第二个参数传递。

use ApiSkeletons\Doctrine\GraphQL\Event\FilterQueryBuilder;
use App\ORM\Entity\Artist;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Schema;
use League\Event\EventDispatcher;

$schema = new Schema([
  'query' => new ObjectType([
      'name' => 'query',
      'fields' => [
          'artists' => [
              'type' => $driver->connection($driver->type(Artist::class)),
              'args' => [
                  'filter' => $driver->filter(Artist::class),
                  'pagination' => $driver->pagination(),
              ],
              'resolve' => $driver->resolve(Artist::class, Artist::class . '.filterQueryBuilder'),
          ],
      ],
  ]),
]);

$driver->get(EventDispatcher::class)->subscribeTo(Artist::class . '.filterQueryBuilder',
    function(FilterQueryBuilder $event) {
        $event->getQueryBuilder()
            ->innerJoin('entity.user', 'user')
            ->andWhere($event->getQueryBuilder()->expr()->eq('user.id', ':userId'))
            ->setParameter('userId', currentUser()->getId())
            ;
    }
);

过滤关联条件

您可以修改用于过滤关联的准则对象。例如,如果您使用软删除,那么您可能希望从一个关联中过滤掉已删除的行。

use ApiSkeletons\Doctrine\GraphQL\Attribute as GraphQL;
use ApiSkeletons\Doctrine\GraphQL\Event\FilterCriteria;
use App\ORM\Entity\Artist;
use League\Event\EventDispatcher;

#[GraphQL\Entity]
class Artist 
{
    #[GraphQL\Field]
    public $id;
    
    #[GraphQL\Field]
    public $name;
    
    #[GraphQL\Association(filterCriteriaEventName: self::class . '.performances.filterCriteria')]
    public $performances;
}

// Add a listener to your driver
$driver->get(EventDispatcher::class)->subscribeTo(
    Artist::class . '.performances.filterCriteria',
    function (FilterCriteria $event): void {
        $event->getCriteria()->andWhere(
            $event->getCriteria()->expr()->eq('isDeleted', false)
        );
    },
);

实体对象类型定义

您可以在创建实体类型之前修改用于定义该类型的数组。这可以用于生成数据等。您必须在定义您的GraphQL模式之前附加到事件。有关详细信息,请参阅详细文档

use ApiSkeletons\Doctrine\GraphQL\Driver;
use ApiSkeletons\Doctrine\GraphQL\Event\EntityDefinition;
use App\ORM\Entity\Artist;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\Type;
use League\Event\EventDispatcher;

$driver = new Driver($entityManager);

$driver->get(EventDispatcher::class)->subscribeTo(
    Artist::class . '.definition',
    static function (EntityDefinition $event): void {
        $definition = $event->getDefinition();

        // In order to modify the fields you must resovle the closure
        $fields = $definition['fields']();

        // Add a custom field to show the name without a prefix of 'The'
        $fields['nameUnprefix'] = [
            'type' => Type::string(),
            'description' => 'A computed dynamically added field',
            'resolve' => static function ($objectValue, array $args, $context, ResolveInfo $info): mixed {
                return trim(str_replace('The', '', $objectValue->getName()));
            },
        ];

        $definition['fields'] = $fields;
    }
);

进一步阅读

详细的文档可在这里找到。