Я использую Symfony 4 с платформой API 2.4.Я не использую Доктрину и поэтому ни Сущностей.У меня есть два класса (не сущности) Facet и Option.Между ними существует связь, поэтому я определяю параметры атрибута в классе Facet, который является коллекцией Option (например, OneToMany в Doctrine).У меня есть свой пользовательский поставщик данных, потому что я получаю эти данные из внешнего API.Я создаю свою коллекцию фасетов с параметрами в этом пользовательском поставщике данных.
В Graphql Doc параметры являются итеративными, но это должен быть ConnectionOption
id: ID!
_id: Int!
name: String!
options: Iterable!
, поэтому я не могу выполнить graphqlзапрос на вложенный объект, у меня ошибка en: поле "options" не должно иметь выбор, так как тип повторяется!не имеет подполей
{
facets {
edges {
node {
id
name
options {
edges {
node {
id
value
count
}
}
}
}
}
}
}
Для информации я попытался использовать аннотацию ORM доктрины, чтобы обойти эту проблему и иметь ConnectionOption вместо итерируемого, и это работает, но когда я выполняю этот запрос graphql, у меня всегда есть пустой массивдля параметров (кажется, что они не сериализованы или даже не существуют)
{
"data": {
"facets": {
"edges": [
{
"node": {
"id": "/api/facets/1",
"name": "facet [1]",
"options": []
}
}
]
}
}
}
Вы можете найти мои классы и мой пользовательский провайдер данных
<?php
namespace App\Model;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use \Doctrine\Common\Collections\Collection;
/**
* @ApiResource()
* Class Facet
*
* @package App\Model
*/
class Facet
{
/**
* @ApiProperty(identifier=true)
* @var int
*/
private $id;
/**
* @var string
*/
private $name;
/**
* @var \App\Model\Option[]
*/
private $options;
public function __construct()
{
$this->options = new ArrayCollection();
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @param int $id
*
* @return Facet
*/
public function setId(int $id): self
{
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @param string $name
*
* @return Facet
*/
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* @return Collection|Option[]
*/
public function getOptions(): Collection
{
return $this->options;
}
public function addOption(Option $option): self
{
if (!$this->options->contains($option)) {
$this->options[] = $option;
$option->setFacet($this);
}
return $this;
}
public function removeOption(Option $option): self
{
if ($this->options->contains($option)) {
$this->options->removeElement($option);
// set the owning side to null (unless already changed)
if ($option->getFacet() === $this) {
$option->setFacet(null);
}
}
return $this;
}
}
<?php
namespace App\Model;
use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
/**
* Class Option
*
* @ApiResource()
* @package App\Model
*/
class Option
{
/**
* @ApiProperty(identifier=true)
* @var int
*/
private $id;
/**
* @var string
*/
private $value;
/**
* @var int
*/
private $count;
/**
* @var Facet
*/
private $facet;
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @param int $id
*
* @return Option
*/
public function setId(int $id): self
{
$this->id = $id;
return $this;
}
/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}
/**
* @param string $value
*
* @return Option
*/
public function setValue(string $value): self
{
$this->value = $value;
return $this;
}
/**
* @return int
*/
public function getCount(): int
{
return $this->count;
}
/**
* @param int $count
*
* @return Option
*/
public function setCount(int $count): self
{
$this->count = $count;
return $this;
}
/**
* @return Facet
*/
public function getFacet(): Facet
{
return $this->facet;
}
/**
* @param Facet $facet
*
* @return Option
*/
public function setFacet(Facet $facet = null): self
{
$this->facet = $facet;
return $this;
}
}
and my custom data provider (just and example)
<?php
namespace App\DataProvider;
use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface;
use ApiPlatform\Core\DataProvider\RestrictedDataProviderInterface;
use App\Model\Facet;
use App\Model\Option;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Class FacetDataProvider
*
* @package App\DataProvider
*/
final class FacetDataProvider implements CollectionDataProviderInterface, RestrictedDataProviderInterface
{
public function supports(string $resourceClass, string $operationName = null, array $context = []): bool
{
return Facet::class === $resourceClass;
}
public function getCollection(string $resourceClass, string $operationName = null)
{
$k = 0;
$collection = new ArrayCollection();
for ($i = 0; $i < 2; $i++) {
$facet = new Facet();
$facet
->setId(++$i)
->setName("facet [$i]");
for ($j = 0; $j < 2; $j++) {
$option = new Option();
$option
->setId($k++)
->setValue("option [$i] [$j]")
->setCount(rand(0, 10))
;
$facet->addOption($option);
}
$collection->add($facet);
}
return $collection;
}
}
Я создаю эти классы как Entity toпоказать ожидаемые результаты для Graphql Doc
id: ID!
_id: Int!
name: String!
options(first: Int after: String): OptionConnection
и при выполнении запроса graphql
{
facets {
edges {
node {
id
name
options {
edges {
node {
id
count
value
}
}
}
}
}
}
}
у меня должен быть такой результат, как
{
"data": {
"facets": {
"edges": [
{
"node": {
"id": "/api/facets/1",
"name": "facet [1]",
"options": {
"edges": [
{
"node": {
"id": "/api/options/1",
"count": 0,
"value": "option [1] [0]"
}
},
{
"node": {
"id": "/api/options/2",
"count": 0,
"value": "option [1] [1]"
}
}
]
}
}
}
]
}
}
}
Спасибо