Skip to main content
Version: 4.3


In GraphQLite, GraphQL queries are created by writing methods in controller classes.

Those classes must be in the controllers namespaces which has been defined when you configured GraphQLite. For instance, in Symfony, the controllers namespace is App\Controller by default.

Simple query#

In a controller class, each query method must be annotated with the @Query annotation. For instance:

namespace App\Controller;
use TheCodingMachine\GraphQLite\Annotations\Query;
class MyController{    #[Query]    public function hello(string $name): string    {        return 'Hello ' . $name;    }}

This query is equivalent to the following GraphQL type language:

Type Query {    hello(name: String!): String!}

As you can see, GraphQLite will automatically do the mapping between PHP types and GraphQL types.

Heads up! If you are not using a framework with an autowiring container (like Symfony or Laravel), please be aware that the MyController class must exist in the container of your application. Furthermore, the identifier of the controller in the container MUST be the fully qualified class name of controller.

About annotations / attributes#

GraphQLite relies a lot on annotations (we call them attributes since PHP 8).

It supports both the old "Doctrine annotations" style (@Query) and the new PHP 8 attributes (#[Query]).

Read the Doctrine annotations VS attributes documentation if you are not familiar with this concept.

Testing the query#

The default GraphQL endpoint is /graphql.

The easiest way to test a GraphQL endpoint is to use GraphiQL or Altair clients (they are available as Chrome or Firefox plugins)

If you are using the Symfony bundle, GraphiQL is also directly embedded.
Simply head to http://[path-to-my-app]/graphiql

Here a query using our simple Hello World example:

Query with a type#

So far, we simply declared a query. But we did not yet declare a type.

Let's assume you want to return a product:

namespace App\Controller;
use TheCodingMachine\GraphQLite\Annotations\Query;
class ProductController{    #[Query]    public function product(string $id): Product    {        // Some code that looks for a product and returns it.    }}

As the Product class is not a scalar type, you must tell GraphQLite how to handle it:

namespace App\Entities;
use TheCodingMachine\GraphQLite\Annotations\Field;use TheCodingMachine\GraphQLite\Annotations\Type;
#[Type]class Product{    // ...
    #[Field]    public function getName(): string    {        return $this->name;    }
    #[Field]    public function getPrice(): ?float    {        return $this->price;    }}

The @Type annotation is used to inform GraphQLite that the Product class is a GraphQL type.

The @Field annotation is used to define the GraphQL fields. This annotation must be put on a public method.

The Product class must be in one of the types namespaces. As for controller classes, you configured this namespace when you installed GraphQLite. By default, in Symfony, the allowed types namespaces are App\Entity and App\Types.

This query is equivalent to the following GraphQL type language:

Type Product {    name: String!    price: Float}

If you are used to Domain driven design, you probably realize that the Product class is part of your domain.

GraphQL annotations are adding some serialization logic that is out of scope of the domain. These are just annotations and for most project, this is the fastest and easiest route.

If you feel that GraphQL annotations do not belong to the domain, or if you cannot modify the class directly (maybe because it is part of a third party library), there is another way to create types without annotating the domain class. We will explore that in the next chapter.