1

我刚开始使用 GraphQL,目前正在使用 webonyx/graphql-php 设置服务器。由于 GraphQL 查询已经必须包含结果数据结构,我不太确定如何获取动态数据。假设我查询包含不同元素类型的内容,我的最终结构应该如下所示:

{
    "data": {
        "dataset": {
            "uuid": "abc...",
            "insertDate": "2018-05-04T12:12:12Z",
            // other metadata
            "content": [
                {
                    "type": "headline",
                    "text": "I am a headline"
                },
                {
                    "type": "image",
                    "src": "http://...",
                    "alt": "I am an image"
                },
                {
                    "type": "review",
                    "rating": 3,
                    "comment": "I am a review"
                },
                {
                    "type": "headline",
                    "text": "I am another headline"
                }
                // other content elements
            ]
        }
    }
}

我怎样才能为这个例子写一个查询?

{
    dataset {
        uuid
        insertDate
        content {
            ????
        }
    }
}

内容部分的类型定义如何?有一组已定义的元素类型(标题、图片、评论等),但它们的顺序和元素数量是未知的,它们只有一个字段,类型,共同点。在我的前端编写查询时,我对内容结构一无所知。内容部分的 graphql-php 类型定义会是什么样子?我在网上找不到任何类似的例子,所以我不确定是否可以在这个用例中使用 GraphQL。作为额外信息,我总是想查询整个内容部分,而不是单个元素或字段,总是要查询所有内容。

4

1 回答 1

1

当您返回一个 Object 类型的数组,但每个单独的项目可能是任意数量的不同 Object 类型之一时,您可以使用 Interface 或 Union。我们可以在这里使用接口,因为所有实现类型共享一个字段 ( type)。

use GraphQL\Type\Definition\InterfaceType;
use GraphQL\Type\Definition\Type;

$content = new InterfaceType([
    'name' => 'Content',
    'description' => 'Available content',
    'fields' => [
        'type' => [
            'type' => Type::nonNull(Type::string()),
            'description' => 'The type of content',
        ]
    ],
    'resolveType' => function ($value) {
        if ($value->type === 'headline') {
            return MyTypes::headline();            
        } elseif ($value->type === 'image') {
            return MyTypes::image();
        } # and so on
    }
]);

实现接口的类型需要在其定义中明确地这样做:

$headline = new ObjectType([
    # other properties 
    'interfaces' => [
        $content
    ]
]);

现在,如果您将content字段的类型更改为 List of content,您可以使用内联片段仅查询特定于每个实现类型的字段:

query GetDataset {
  dataset {
    uuid
    insertDate
    content {
      type # this field is shared, so it doesn't need an inline fragment
      ... on Headline {
        text
      }
      ... on Image {
        src
        alt
      }
      # and so on
    }
  }
}

有关更多详细信息,请参阅文档

于 2019-01-25T13:34:06.580 回答