Запросить неизвестную структуру данных в GraphQL - PullRequest
0 голосов
/ 25 января 2019

Я только начал работать с 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 для этого варианта использования.В качестве дополнительной информации я всегда хочу запросить весь раздел контента, а не один элемент или поле, всегда все.

1 Ответ

0 голосов
/ 25 января 2019

Когда вы возвращаете массив типов объектов, но каждый отдельный элемент может быть одним из любого числа различных типов объектов, вы можете использовать интерфейс или объединение.Здесь мы можем использовать Интерфейс, так как все реализующие типы совместно используют поле (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 на Список 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
    }
  }
}

Пожалуйста, смотрите документы для более подробной информации.

...