Skip to content

reydajp/cakephp-graphql-plugin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CI Coverage Packagist PHP License: MIT

CakeGraphQL

CakeGraphQL is a CakePHP 5 plugin for GraphQL endpoint routing, endpoint-level authentication, engine selection, and GraphQLite integration.

The plugin owns the HTTP endpoint and GraphQL engine wiring. The host application owns resolver classes, entity/type annotations, authentication provider setup, field-level authorization, and business logic.

Requirements

  • PHP 8.3 or newer
  • CakePHP 5
  • GraphQLite 8
  • Webonyx GraphQL PHP 15

Installation

composer require reydajp/cake-graphql

Load the plugin in the host application:

// src/Application.php
public function bootstrap(): void
{
    parent::bootstrap();

    $this->addPlugin('CakeGraphQL');
}

Configuration

Configure the plugin with the Graphql key:

// config/app_local.php or config/app.php
'Graphql' => [
    'path' => '/api/graphql',
    'engine' => 'Graphqlite',
    'authenticated' => true,
    'engines' => [
        'Graphqlite' => [
            'queries' => [
                App\Graphql\UsersQuery::class,
            ],
            'types' => [
                App\Model\Entity\User::class,
            ],
            'cache' => 'default',
            'debug' => false,
            'maxDepth' => 10,
            'maxComplexity' => 200,
        ],
    ],
],

The plugin registers the configured route and attaches route-specific GraphQL middleware. CakePHP routing middleware must run as usual in the host application. maxDepth and maxComplexity reject overly nested or expensive GraphQL operations before resolver execution.

See docs/configuration.md for the full configuration contract.

Resolver Example

<?php
declare(strict_types=1);

namespace App\Graphql;

use Cake\ORM\Locator\LocatorAwareTrait;
use TheCodingMachine\GraphQLite\Annotations\Query;

final class UsersQuery
{
    use LocatorAwareTrait;

    #[Query]
    public function users(int $limit = 50): array
    {
        $limit = max(1, min($limit, 100));

        return $this->fetchTable('Users')->find()->limit($limit)->all()->toList();
    }
}

Register resolver classes explicitly in Graphql.engines.Graphqlite.queries. CakeGraphQL does not scan broad application namespaces by default.

See docs/graphqlite.md for CakePHP examples using GraphQLite #[Query], #[Type], and #[Field] attributes.

Error Responses

CakeGraphQL returns normal GraphQL partial responses for resolver and field errors after execution starts: HTTP 200, partial data, and an errors entry with the field path. Cake HTTP exceptions thrown by resolvers expose their client-safe message, for example User not found.

Endpoint-level authentication still happens before GraphQL execution. When authenticated is true and the request has no Cake identity, the endpoint returns HTTP 401. Resolver-level authentication errors from GraphQLite attributes such as #[Logged] are GraphQL execution errors and return HTTP 200.

Bake Command

Generate a collection query resolver:

bin/cake bake graphql query Users

Generate a single-record query resolver:

bin/cake bake graphql query Users --single

Generate into a custom namespace:

bin/cake bake graphql query Users --namespace App\\Api\\Graphql

By default, the command updates Graphql.engines.Graphqlite.queries in config/app_local.php or config/app.php. Use --no-config to skip that update.

See docs/bake.md for details.

Authentication

When authenticated is true, CakeGraphQL rejects requests before GraphQL execution if the request has no identity attribute. This relies on the host application's Cake Authentication middleware running before the GraphQL route middleware.

CakeGraphQL bridges Cake Authentication's request identity into GraphQLite's authentication service. GraphQLite resolvers can inject the current Cake user with #[InjectUser]:

use App\Model\Entity\User;
use TheCodingMachine\GraphQLite\Annotations\InjectUser;
use TheCodingMachine\GraphQLite\Annotations\Query;

final class UsersQuery
{
    #[Query]
    public function me(#[InjectUser] ?User $user): ?User
    {
        return $user;
    }
}

If the injected parameter is not nullable, GraphQLite requires a logged-in user for that field. #[Logged] also uses the bridged Cake identity.

The bridge reads Cake's request identity attribute. AuthenticationComponent remains controller-only and is not available inside resolver classes.

Field-level authorization is intentionally engine-specific. GraphQLite attributes such as #[Right] or #[Security] require GraphQLite authorization services; CakeGraphQL does not currently bridge Cake Authorization into those services.

See docs/graphqlite.md for examples and the current integration boundary.

Commands

composer test
composer validate --strict
find src tests -name '*.php' -exec php -l {} \;

License

MIT. See LICENSE.

About

GraphQL integration plugin for CakePHP using Webonyx GraphQL PHP and GraphQLite.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages