Extending a type
Fields exposed in a GraphQL type do not need to be all part of the same class.
Use the @ExtendType
annotation to add additional fields to a type that is already declared.
Let's assume you have a Product
class. In order to get the name of a product, there is no getName()
method in
the product because the name needs to be translated in the correct language. You have a TranslationService
to do that.
namespace App\Entities;
use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\Type;
#[Type]
class Product
{
// ...
#[Field]
public function getId(): string
{
return $this->id;
}
#[Field]
public function getPrice(): ?float
{
return $this->price;
}
}
// You need to use a service to get the name of the product in the correct language.
$name = $translationService->getProductName($productId, $language);
Using @ExtendType
, you can add an additional name
field to your product:
namespace App\Types;
use TheCodingMachine\GraphQLite\Annotations\ExtendType;
use TheCodingMachine\GraphQLite\Annotations\Field;
use App\Entities\Product;
#[ExtendType(class: Product::class)]
class ProductType
{
private $translationService;
public function __construct(TranslationServiceInterface $translationService)
{
$this->translationService = $translationService;
}
#[Field]
public function getName(Product $product, string $language): string
{
return $this->translationService->getProductName($product->getId(), $language);
}
}
Let's break this sample:
#[ExtendType(class: Product::class)]
With the @ExtendType
annotation, we tell GraphQLite that we want to add fields in the GraphQL type mapped to
the Product
PHP class.
class ProductType
{
private $translationService;
public function __construct(TranslationServiceInterface $translationService)
{
$this->translationService = $translationService;
}
// ...
}
- The
ProductType
class must be in the types namespace. You configured this namespace when you installed GraphQLite. - The
ProductType
class is actually a service. You can therefore inject dependencies in it (like the$translationService
in this example)
ProductType
class must exist in the container of your application and the container identifier MUST be the fully qualified class name.If you are using the Symfony bundle (or a framework with autowiring like Laravel), this is usually not an issue as the container will automatically create the controller entry if you do not explicitly declare it.
#[Field]
public function getName(Product $product, string $language): string
{
return $this->translationService->getProductName($product->getId(), $language);
}
The @Field
annotation is used to add the "name" field to the Product
type.
Take a close look at the signature. The first parameter is the "resolved object" we are working on. Any additional parameters are used as arguments.
Using the "Type language" notation, we defined a type extension for the GraphQL "Product" type:
Extend type Product {
name(language: !String): String!
}