Autowiring services
GraphQLite can automatically inject services in your fields/queries/mutations signatures.
Some of your fields may be computed. In order to compute these fields, you might need to call a service.
Most of the time, your @Type
annotation will be put on a model. And models do not have access to services.
Hopefully, if you add a type-hinted service in your field's declaration, GraphQLite will automatically fill it with
the service instance.
Sample
Let's assume you are running an international store. You have a Product
class. Each product has many names (depending
on the language of the user).
- PHP 8
- PHP 7
namespace App\Entities;
use TheCodingMachine\GraphQLite\Annotations\Autowire;
use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\Type;
use Symfony\Component\Translation\TranslatorInterface;
#[Type]
class Product
{
// ...
#[Field]
public function getName(
#[Autowire]
TranslatorInterface $translator
): string
{
return $translator->trans('product_name_'.$this->id);
}
}
namespace App\Entities;
use TheCodingMachine\GraphQLite\Annotations\Autowire;
use TheCodingMachine\GraphQLite\Annotations\Field;
use TheCodingMachine\GraphQLite\Annotations\Type;
use Symfony\Component\Translation\TranslatorInterface;
/**
* @Type()
*/
class Product
{
// ...
/**
* @Field()
* @Autowire(for="$translator")
*/
public function getName(TranslatorInterface $translator): string
{
return $translator->trans('product_name_'.$this->id);
}
}
When GraphQLite queries the name, it will automatically fetch the translator service.
Symfony\Component\Translation\TranslatorInterface
.Best practices
It is a good idea to refrain from type-hinting on concrete implementations. Most often, your field declaration will be in your model. If you add a type-hint on a service, you are binding your domain with a particular service implementation. This makes your code tightly coupled and less testable.
#[Field] public function getName(#[Autowire] MyTranslator $translator): string
Instead, be sure to type-hint against an interface.
#[Field] public function getName(#[Autowire] TranslatorInterface $translator): string
By type-hinting against an interface, your code remains testable and is decoupled from the service implementation.
Fetching a service by name (discouraged!)
Optionally, you can specify the identifier of the service you want to fetch from the controller:
- PHP 8
- PHP 7
#[Autowire(identifier: "translator")]
/**
* @Autowire(for="$translator", identifier="translator")
*/
Alternative solution
You may find yourself uncomfortable with the autowiring mechanism of GraphQLite. For instance maybe:
- Your service identifier in the container is not the fully qualified class name of the service (this is often true if you are not using a container supporting autowiring)
- You do not want to inject a service in a domain object
- You simply do not like the magic of injecting services in a method signature
If you do not want to use autowiring and if you still need to access services to compute a field, please read on the next chapter to learn how to extend a type.