Skip to content

GraphQL, single custom provider fro all nested data #8076

@bogdandubyk

Description

@bogdandubyk

API Platform version(s) affected: 3.1.11

Description
So I have a massive resource with a lot of nested data, but all that data should be requested only by the root id, here I'll show a simplified version.
Product :

  • id
  • shopId
  • name
  • Facility
    • id
    • name
    • Varaints[]
      - sku
      - on

And as I mentioned all operations should be done only on the product, so if I want to get some data I need to make a query like

{
  product(id: "/products/1", shopId: 234234) {
    id, name, facility {name,variants{
      edges {
        node {
          sku
        }
      }
    }}
  }
}

Additionally, I'm not using doctrine and want all data to come from a single custom provider. All works properly for product and facility but not for variants, I'm getting an error Provider not found on operation \"collection_query\" but I do not want to have a separate provider for variants all that data should come from a main product provider.

How to reproduce
Product

#[ApiResource(
    provider: ProductProvider::class,
    graphQlOperations: [
        new Query(
            args: [
                'id' => [
                    'type' => 'ID!',
                    'description' => 'The ID of the product.',
                ],
                'shopId' => [
                    'type' => 'Int!',
                    'description' => 'The ID of the shop.',
                ],
            ]
        ),
        new QueryCollection(
        ),
    ]
)]
class Product
{
    public function __construct(
        private string       $id,
        private int          $shopId,
        public  string       $name,
        public Facility $facility,
    ){}

    public function getId()
    {
        return $this->id;
    }

    public function getShopId()
    {
        return $this->shopId;
    }
}

Facility (here as I do not want any operations to be performed directly to facility I set empty list as graphQlOperations)

#[ApiResource(graphQlOperations: [],)]
final class Facility
{
    /**
     * @param Variant[] $variants
     */
    public function __construct(
        public int $id,
        public string $$name,
        public array $variants
    )
    {
    }
}

Variant

#[ApiResource(
    graphQlOperations: []
)]
final class Variant
{
    public function __construct(
        public bool $on,
        public string $sku,
    )
    {
    }
}

and Here is ProductProvider

final class ProductProvider implements ProviderInterface
{
    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|null|array
    {

        $data = ... // logic to get product data
        
     $product = new Product(
            $data['_id'],
            $data['shop_id'],
            $data['name'],
            new Facility(
                $data['facility']['id'],
                explode(',', $data['facility']['name']),
                array_map(
                    fn(array $variant) => new Variant(
                        (bool)$variant['on'],
                        $variant['sku'],
                    ), $data['facility']['variants']
                )
            ),
        );


        if ($operation instanceof QueryCollection) {
            return new ArrayPaginator([$product], 0, 1);
        }

        return $product;

so as mentioned earlier if I run query like this

{
  product(id: "/products/1", shopId: 234234) {
    id, name,, facility {name,variants{
      edges {
        node {
          sku
        }
      }
    }}
  }
}

I'm getting an error Provider not found on operation \"collection_query\", but this query works:

{
  product(id: "/products/586b8f112f7d8059668e5f73", shopId: 234234) {
    id, name, facility {name}
}

Possible Solution
I do not what can be the solution and if it's even a bug, but I do not want to have separate providers and query each sub-data separately, I want all data to come from one provider. I tried to reach out in the Slack channel with a few questions for the last few months and did not get answers to either, so writing here

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions