Extend the data type

Let’s try to extend the GraphQL schema a little so we are able to fetch information about the manufacturer assigned to a product.

Query

query {
    product (
        id: "dc5ffdf380e15674b56dd562a7cb6aec"
    ){
        title
        manufacturer {
            id
            title
        }
    }
}

Response

{
    "data": {
        "product": {
            "title": "Kuyichi Ledergürtel JEVER",
            "manufacturer": {
                "id": "9434afb379a46d6c141de9c9e5b94fcf",
                "title": "Kuyichi"
            }
        }
    }
}

Important

As stated in the Specification section, if no manufacturer can be found for the product, we get a null.

We might be tempted to simply extend the product DataType to have a field for the manufacturer id, but please check the hints given in Specification section. The manufacturer should get its own datatype and then get a relation to the product. So let’s add the Manufacturer Data Type:

src/Manufacturer/DataType/Manufacturer.php
<?php

declare(strict_types=1);

namespace MyVendor\GraphQL\MyGraph\Manufacturer\DataType;

use OxidEsales\Eshop\Application\Model\Manufacturer as EshopManufacturerModel;
use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\Type;
use TheCodingMachine\GraphQLite\Types\ID;

/**
 * @Type()
 */
final class Manufacturer
{
    /** @var EshopManufacturerModel */
    private $manufacturer;

    public function __construct(
        EshopManufacturerModel $manufacturer
    ) {
        $this->manufacturer = $manufacturer;
    }

    /**
     * @Field()
     */
    public function getId(): ID
    {
        return new ID($this->manufacturer->getId());
    }

    /**
     * @Field()
     */
    public function getTitle(): string
    {
        return $this->manufacturer->getTitle();
    }
}

Also we need the connection to OXID eShop’s OxidEsales\Eshop\Application\Model\Article::getManufacturer() which belongs in the infrastructure layer:

src/Manufacturer/Infrastructure/Manufacturer.php
<?php

declare(strict_types=1);

namespace MyVendor\GraphQL\MyGraph\Manufacturer\Infrastructure;

use OxidEsales\Eshop\Application\Model\Manufacturer as EshopManufacturerModel;
use MyVendor\GraphQL\MyGraph\Product\DataType\Manufacturer as ManufacturerDataType;
use MyVendor\GraphQL\MyGraph\Product\DataType\Product as ProductDataType;

final class Product
{
    public function manufacturerByProduct(ProductDataType $product): ?ManufacturerDataType
    {
        /** @var null|EshopManufacturerModel $manufacturer */
        $manufacturer = $product->getEshopModel()->getManufacturer();

        if ($manufacturer === null) {
            return null;
        }

        return new ManufacturerDataType(
            $manufacturer
        );
    }
}

And then we relate it to the product by implementing a RelationService and using the @ExtendType() notation.

src/Product/Service/RelationService.php
<?php

/**
 * Copyright © OXID eSales AG. All rights reserved.
 * See LICENSE file for license details.
 */

declare(strict_types=1);

namespace MyVendor\GraphQL\MyGraph\Product\Service;

use MyVendor\GraphQL\MyGraph\Product\DataType\Manufacturer;
use MyVendor\GraphQL\MyGraph\Product\DataType\Product;
use MyVendor\GraphQL\MyGraph\Product\Infrastructure\Product as ProductInfrastructure;
use TheCodingMachine\GraphQLite\Annotations\ExtendType;
use TheCodingMachine\GraphQLite\Annotations\Field;

/**
 * @ExtendType(class=Product::class)
 */
final class RelationService
{
    /** @var ProductInfrastructure */
    private $productInfrastructure;

    public function __construct(
        ProductInfrastructure $productInfrastructure
    ) {
        $this->productInfrastructure = $productInfrastructure;
    }

    /**
     * @Field()
     */
    public function manufacturer(Product $product): ?Manufacturer
    {
        return $this->productInfrastructure
                    ->manufacturerByProduct($product);
    }
}

Please remember as this is a new type for GraphQL, it needs to be registered in the NamespaceMapper::getTypeNamespaceMapping() method!

At this point, running our extended query will be possible.