Extending an input type
@Factory
tag, read first the "input types" guide.Fields exposed in a GraphQL input type do not need to be all part of the factory method.
Just like with output type (that can be extended using the ExtendType
annotation), you can extend/modify
an input type using the @Decorate
annotation.
Use the @Decorate
annotation to add additional fields to an input type that is already declared by a @Factory
annotation,
or to modify the returned object.
@Decorate
annotation is very useful in scenarios where you cannot touch the @Factory
method. This can happen if the @Factory
method is defined in a third-party library or if the @Factory
method is part of auto-generated code.Let's assume you have a Filter
class used as an input type. You most certainly have a @Factory
to create the input type.
class MyFactory
{
/**
* @Factory()
*/
public function createFilter(string $name): Filter
{
// Let's assume you have a flexible 'Filter' class that can accept any kind of filter
$filter = new Filter();
$filter->addFilter('name', $name);
return $filter;
}
}
Assuming you cannot modify the code of this factory, you can still modify the GraphQL input type generated by adding a "decorator" around the factory.
class MyDecorator
{
/**
* @Decorate(inputTypeName="FilterInput")
*/
public function addTypeFilter(Filter $filter, string $type): Filter
{
$filter->addFilter('type', $type);
return $filter;
}
}
In the example above, the "Filter" input type is modified. We add an additional "type" field to the input type.
A few things to notice:
- The decorator takes the object generated by the factory as first argument
- The decorator MUST return an object of the same type (or a sub-type)
- The decorator CAN contain additional parameters. They will be added to the fields of the GraphQL input type.
- The
@Decorate
annotation must contain ainputTypeName
attribute that contains the name of the GraphQL input type that is decorated. If you did not specify this name in the@Factory
annotation, this is by default the name of the PHP class + "Input" (for instance: "Filter" => "FilterInput")
MyDecorator
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.