GraphQL with GraphQLite integration

TDBM offers a native integration with GraphQLite

GraphQLite is a PHP library to easily develop a GraphQL library. GraphQLite core principle is to declare GraphQL types using PHP annotations.

For instance:

/**
 * @Type()
 */
class Product
{
    // ...

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

However, in TDBM, the classes and getters are generated by TDBM itself. The getters are in the generated abstract classes and you cannot edit those files (as they are overwritten by TDBM each time you generate the beans and DAOs).

TDBM-GraphQL is a library that can read annotations from the database model and forward those annotations to the PHP classes.

You put @Type or @Field annotations in your database tables and columns and TDBM will generate these annotations in the beans and DAOs.

Installation

Installation for Symfony

Open a terminal in your current project directory and run:

$ composer require thecodingmachine/tdbm-graphql-bundle

If you are using Flex, you are done. Jump to the Annotating your DB model section.

Not using Flex? Enable the library by adding it to the list of registered bundles in the config/bundles.php file:

config/bundles.php

return [
    // ...
    'TheCodingMachine\\Tdbm\Graphql\\Bundle\\TheCodingMachineTdbmGraphqlBundle' => ['all' => true],
}

Configuration

Configuration is only needed for tdbm-graphql-bundle version 3.x. Starting with tdbm-graphql-bundle v4, there is no configuration necessary, you can completely skip this part.

The parameters are stored in the config/packages/tdbm-graphql.yaml file.

By default, generated types will go into App\Types.

If your default namespace for your application is not App, you should open this tdbm-graphql.yaml file and customize the tdbm-graphl.type_namespace and tdbm-graphl.generated_type_namespace (optionnal) to match your application namespace.

Here is a configuration file with all available options:

config/packages/tdbm-graphql.yaml

tdbm-graphql:
    type_namespace: App\Types
    generated_type_namespace: App\Types\Generated

Manual installation

Open a terminal in your current project directory and run:

$ composer require thecodingmachine/tdbm-graphql

The tdbm-graphql package provides a GraphQLTypeAnnotator. This class alters the way TDBM generates the beans and DAOs.

You must create an instance of this class and register it in the TDBM configuration:

use TheCodingMachine\Tdbm\GraphQL\GraphQLTypeAnnotator;
use TheCodingMachine\TDBM\Configuration;

// The parameter passed is the namespace in which the classes will be generated
$annotator = new GraphQLTypeAnnotator('App\\Types\\');
$configuration = new Configuration(
    'App\\Beans',
    'App\\DAOs',
    $connection,
    null,
    new ArrayCache(),
    null,
    null,
    [ $annotator ], // The annotator must be passed to the $generatorListeners parameter
    null,
    [ $annotator ] // and also to the $codeGeneratorListeners parameter
);

Annotating your DB model

In order to expose a bean as a GraphQL type, you must annotate the database model.

You can use the same annotations as in GraphQLite (but you must make sure they are fully qualified).

For each bean, you must put the @Type annotation in the class comment and the @Field annotation in each column you want to expose.

ALTER TABLE users COMMENT '@TheCodingMachine\\GraphQLite\\Annotations\\Type';
ALTER TABLE users MODIFY COLUMN `name` VARCHAR(255) NOT NULL COMMENT '@TheCodingMachine\\GraphQLite\\Annotations\\Field';

Adding comments on each column can be tedious. We highly recommend to use the TDBM Fluid Schema Builder to create the schema instead. The library provides a number of helpers to create the annotations for you:

$db->table('users')
   ->column('name')->string(50)->graphqlField();
   // The graphqlField() method will add the @Field annotation on the column AND the @Type annotation on the class at once.

Once your data model is commented with the annotations, you just have to regenerate the TDBM DAOs and beans:

bin/console tdbm:generate

You can check the getters in the generated beans, they should be annotated with the GraphQLite's @Field annotation.

Additional annotations supported

TDBM-GraphQL supports additional annotations to manage the fields' visibility:

ALTER TABLE users MODIFY COLUMN `name` VARCHAR(255) NOT NULL COMMENT '
  @TheCodingMachine\\GraphQLite\\Annotations\\Field
  @TheCodingMachine\\GraphQLite\\Annotations\\Logged
  @TheCodingMachine\\GraphQLite\\Annotations\\Right("CAN_SEE_NAME")
  @TheCodingMachine\\GraphQLite\\Annotations\\FailWith(null)
';

You can find more about these security annotations in the GraphQLite documentation.

You can also create these annotations using the TDBM Fluid Schema Builder.

$db->table('users')
   ->column('name')->string(50)->graphqlField()
   ->logged()->right('CAN_SEE_NAME')->failWith(null);

Use your beans as input types

TDBM will automatically annotate the xxxDao::getById() method with a @Factory annotation. As a result, you can directly inject you beans as arguments in your GraphQL queries.

For instance:

class ProductController
{
    // ...

    /**
     * @Query()
     * @return ProductResultIterator
     */
    public function getProducts(Category $category): array
    {
        // ...
    }
}

Assuming "Category" is a bean, TDBM-GraphQL will automatically fetch the bean from the database and populate the $category argument with it.

Your GraphQL query will look like this:

{
    products(category: { id: 42 }) {
        id
        name
    }
}

Found a typo? Something is wrong in this documentation? Just fork and edit it!