99designs/graphql-bundle

Symfony GraphQl 扩展包

v1.0.1 2023-08-15 04:12 UTC

This package is auto-updated.

Last update: 2024-09-15 06:25:25 UTC


README

这是一个基于纯 PHP GraphQL 服务器实现 的扩展包

此扩展包为您提供以下功能

  • 完全兼容 GraphQL RFC 规范
  • 敏捷的面向对象结构,用于构建您的 GraphQL 模式
  • 直观的类型系统,使您能够快速构建项目并保持一致性
  • 为开发的 GraphQL 模式内置验证
  • 带有大量示例的详细文档类
  • 自动创建端点 /graphql 以处理请求

有一个简单的演示应用程序来展示我们如何构建我们的 API,请参阅 GraphQLDemoApp

目录

安装

我们假设您已经安装了 composer,如果没有,请从 官方网站 安装。
如果您需要安装 Symfony 框架的帮助,请在此链接 https://symfony.ac.cn/doc/current/book/installation.html

安装 Symfony 的快捷方式:composer create-project symfony/framework-standard-edition my_project_name

一旦您的 composer 开始运行,您就可以安装 GraphQL 扩展包了。
转到您的项目文件夹并运行

composer require youshido/graphql-bundle

然后在您的 app/AppKernel.php 文件中启用扩展包

new Youshido\GraphQLBundle\GraphQLBundle(),

将路由引用添加到 app/config/routing.yml

graphql:
    resource: "@GraphQLBundle/Controller/"

graphql:
    resource: "@GraphQLBundle/Resources/config/route.xml"

如果您还没有配置 Web 服务器,可以使用捆绑版本,只需运行 php bin/console server:run

让我们检查您是否已经正确完成了一切——尝试访问网址 localhost:8000/graphql
您应该会收到以下错误信息的 JSON 响应

{"errors":[{"message":"Schema class does not exist"}]}

这是因为处理器尚未指定 GraphQL 模式。您需要创建一个 GraphQL 模式类并将其设置在您的 app/config/config.yml 文件中。

有一种方法可以采用内联方法而不创建模式类,为了这样做,您必须定义自己的 GraphQL 控制器并使用处理器的 ->setSchema 方法设置模式。

创建模式类的最快方法是使用此扩展包提供的生成器

php bin/console graphql:configure AppBundle

在此 AppBundle 是类将生成的扩展包的名称。
您将被要求确认创建一个类。

在您添加了参数到配置文件后,尝试在浏览器中访问以下链接—— http://localhost:8000/graphql?query={hello(name:World)}

或者,您可以在控制台中使用 CURL 客户端执行相同的请求
curl http://localhost:8000/graphql --data "query={ hello(name: \"World\") }"

从测试模式收到的成功响应将被显示

{"data":{"hello":"world!"}}

这意味着您已经配置了 Symfony 框架的 GraphQL 扩展包,现在可以构建您的 GraphQL 模式

下一步是执行以下操作以链接 GraphiQL 探索器的资源

php bin/console assets:install --symlink

现在您可以在 http://localhost:8000/graphql/explorer 访问它

Symfony 功能

类 AbstractContainerAwareField

AbstractContainerAwareField 类用于自动将容器传递给字段,并增加在 resolve 函数中使用容器的能力

class RootDirField extends AbstractContainerAwareField
{

    /**
     * @inheritdoc
     */
    public function getType()
    {
        return new StringType();
    }

    /**
     * @inheritdoc
     */
    public function resolve($value, array $args, ResolveInfo $info)
    {
        return $this->container->getParameter('kernel.root_dir');
    }

    /**
     * @inheritdoc
     */
    public function getName()
    {
        return 'rootDir';
    }

服务方法作为可调用对象

能够将服务方法作为 resolve 可调用函数传递

$config->addField(new Field([
    'name'    => 'cacheDir',
    'type'    => new StringType(),
    'resolve' => ['@resolve_service', 'getCacheDir']
]))

事件

你可以使用 Symfony 事件调度器来控制在解析 GraphQL 查询时发生的特定事件

namespace ...\...\..;

use Youshido\GraphQL\Event\ResolveEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MyGraphQLResolveEventSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            'graphql.pre_resolve'  => 'onPreResolve',
            'graphql.post_resolve' => 'onPostResolve'
        ];
    }

    public function onPreResolve(ResolveEvent $event)
    {
		//$event->getFields / $event->getAstFields()..
    }

    public function onPostResolve(ResolveEvent $event)
    {
		//$event->getFields / $event->getAstFields()..
    }
}

配置

现在配置你的订阅者,以便捕获事件。这可以通过在 Symfony 中使用 XML、Yaml 或 PHP 来完成。

<service id="my_own_bundle.event_subscriber.my_graphql_resolve_event_subscriber" class="...\...\...\MyGraphQLResolveEventSubscriber">
	<tag name="graphql.event_subscriber" />
</service>

安全性

Bundle 提供了两种保护应用程序的方式:使用黑白名单或使用安全投票者。

黑白名单

用于保护某些根操作。要启用它,你需要在你的 config.yml 文件中写入以下内容

graphql:

  #...

  security:
    black_list: ['hello'] # or white_list: ['hello']

使用安全投票者

用于保护任何字段解析,并支持两种类型的保护:根操作和任何其他字段解析(包括内部字段、标量类型字段、根操作)。要使用你指定的逻辑保护根操作,你需要在配置中启用它,并使用 SecurityManagerInterface::RESOLVE_ROOT_OPERATION_ATTRIBUTE 属性。同样,为了启用字段保护,也需要这样做,但在这个情况下使用 SecurityManagerInterface::RESOLVE_FIELD_ATTRIBUTE 属性。有关投票者的官方文档

注意:启用字段安全会导致性能显著下降

配置示例

graphql:
    security:
        guard:
            field: true # for any field security
            operation: true # for root level security

投票者示例(添加到你的 services.yml 文件中,带有 security.voter 标签)

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Youshido\GraphQL\Execution\ResolveInfo;
use Youshido\GraphQLBundle\Security\Manager\SecurityManagerInterface;

class GraphQLVoter extends Voter
{

    /**
     * @inheritdoc
     */
    protected function supports($attribute, $subject)
    {
        return in_array($attribute, [SecurityManagerInterface::RESOLVE_FIELD_ATTRIBUTE, SecurityManagerInterface::RESOLVE_ROOT_OPERATION_ATTRIBUTE]);
    }

    /**
     * @inheritdoc
     */
    protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
    {
        // your own validation logic here

        if (SecurityManagerInterface::RESOLVE_FIELD_ATTRIBUTE == $attribute) {
            /** @var $subject ResolveInfo */
            if ($subject->getField()->getName() == 'hello') {
                return false;
            }

            return true;
        } elseif (SecurityManagerInterface::RESOLVE_ROOT_OPERATION_ATTRIBUTE == $attribute) {
            /** @var $subject Query */
            if ($subject->getName() == '__schema') {
                return true;
            }
        }
    }
}

GraphiQL 扩展

要运行 graphiql 扩展,只需尝试访问 http://your_domain/graphql/explorer

文档

所有详细文档可在主 GraphQL 存储库中找到 – http://github.com/youshido/graphql/