Laravel GraphQL Gotchas
Tags: laravel, graphql, lighthouse
Published: 2018-11-30 01:15:49

---
title: Laravel GraphQL Gotchas
published: true
tags: Laravel, GraphQL, Lighthouse
canonical_url: https://miguelpiedrafita.com/laravel-graphql-gotchas/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/28ib22tf23iw35335fue.png
---
For a new project I'm working on, I had to code a GraphQL API with Laravel. I pulled in the Lighthouse GraphQL Server package, which was f[eatured on Laravel News some weeks ago](https://laravel-news.com/lighthouse-graphql-server-for-laravel) and started to follow [the documentation](https://lighthouse-php.netlify.com/). While most things worked as I expected, I spent quite a lot of time debugging some that didn't and weren't documented anywhere, so after I figured them out, I thought this article could help others facing the same position.

## Password length checking

Imagine you have a createUser mutation to, uhhh, create users. It's using the `@bcrypt` directive (provided by Lighthouse) to make our life easier: The code is as follows:

```graphql
type Mutation {
    createUser(
        name: String @rules(apply: ["required"])
        email: String @rules(apply: ["required", "email", "unique:users,email"])
        password: String @rules(apply: ["required", "string", "min:6", "max:255"]) @bcrypt
    ): User @create(model: "App\\User")
}
```

You'd expect a password with two characters to throw an error, but it actually works. Apparently, the client hashes the password and then performs validation. As a workaround, you can move the migration's logic to a controller by executing `php artisan lighthouse:mutation CreateUser` and then manually hashing and creating a User.

```php
<?php

namespace App\Http\GraphQL\Mutations;

use App\User;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class CreateUser
{
    public function resolve($rootValue, array $args, GraphQLContext $context = null, ResolveInfo $resolveInfo)
    {
        return User::create([
            'username' => $args['username'],
            'email' => $args['email'],
            'password' => bcrypt($args['password']),
        ]);
    }
}
```

## Policies

Lighthouse features a `@can` directive to check if the user's authorized to perform the specified action, but it only works for generic models (meaning you can check if the user has permissions to create models, but you can't check permissions like deletion against a singular model). The workaround for this is, again, move your mutation/query to a controlling, and check for permission there.

```php
<?php

namespace App\Http\GraphQL\Mutations;

use App\SecureResource;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class DoSecureStuff
{
    public function resolve($rootValue, array $args, GraphQLContext $context = null, ResolveInfo $resolveInfo)
    {
        abort_unless(request()->user()->can('update', SecretResource::find($args['id']));
        
        // do stuff
    }
}
```

## Organizing routing

If you're using this library in a relatively-large project, your `schema.graphql` might be a +200 LOC mess. If you wanna tidy it up a little bit, you can divide it into smaller files like `user.graphql` or `pages.graphql` and include them in your main schema:

```graphql
#import user.graphql
#import pages.graphql
#import something-else.graphql
```

But be careful! You can only have one `Query` and one `Mutation` type. You'll have to extend the others:

```graphql
extend type Query {
    pages: [Page!]! @paginate(type: "paginator" model: "App\\Page")
}

extend type Mutation {
    deletePage(
        id: ID! @rules(apply: ["required"])
    ): User @delete(model: "App\\Page")
}
```

## Debugging GraphQL errors

This library is exceptionally difficult to debug, because the GraphQL handler catches all the errors to avoid failing to the client, and returns `null` instead of the result. To overcome this, you can update the configuration file for the package (`lighthouse.php`):

```php
/*
    |--------------------------------------------------------------------------
    | Debug
    |--------------------------------------------------------------------------
    |
    | Control the debug level as described in http://webonyx.github.io/graphql-php/error-handling/
    | Debugging is only applied if the global Laravel debug config is set to true.
    |
    */
- 'debug' => Debug::INCLUDE_DEBUG_MESSAGE | Debug::INCLUDE_TRACE,
+ 'debug' => Debug::INCLUDE_DEBUG_MESSAGE | Debug::RETHROW_INTERNAL_EXCEPTIONS
```

## Conclusion

While it still needs some work, this package makes it incredibly easy to develop GraphQL APIs with Laravel. And, if you're using this library in a project, I'd recommend you to spend five minutes of your time writing an appreciation note to [the collaborators](https://github.com/nuwave/lighthouse/graphs/contributors). They'll surely appreciate it!

_Liked this article? Consider [supporting my work](https://miguelpiedrafita.com/patreon)._