Graphql-laravel: Handling many-to-many pivots?

Created on 18 Nov 2016  路  5Comments  路  Source: rebing/graphql-laravel

I've been trying out graphql with laravel and I was wondering how should I approach pivots in eloquent?

This package can handle something like:

'posts' => [
                'type' => Type::listOf(GraphQL::type('Post')),
                'description' => 'The user posts',
                // Can also be defined as a string
                'always' => ['title', 'body'],
            ]

But when it comes to belongsToMany relationships how should I attach withPivot columns in graphql?

Most helpful comment

Let's say we have a pivot table 'post_user' (post_id, user_id, seen_at) and you need the seen_at pivot. The 'posts' relation is defined under User model with $this->belongsToMany(Post::class)->withPivot(['seen_at']);

Now we create a UserPostsQuery, which resolves User::with('posts')->get(); and returns type Type::listOf(GraphQL::type('post')). The PostType should then have the following field:

'user_seen_at' => [
    'type' => Type::int(),
    'description' => 'Timestamp, when the user saw the post',
    'selectable' => false,
    'resolve' => function($post) {return object_get($post, 'pivot.seen_at');},
]

You can resolve it in a separate function resolveUserSeenAt($post) as well.
Hope it helps!

All 5 comments

Let's say we have a pivot table 'post_user' (post_id, user_id, seen_at) and you need the seen_at pivot. The 'posts' relation is defined under User model with $this->belongsToMany(Post::class)->withPivot(['seen_at']);

Now we create a UserPostsQuery, which resolves User::with('posts')->get(); and returns type Type::listOf(GraphQL::type('post')). The PostType should then have the following field:

'user_seen_at' => [
    'type' => Type::int(),
    'description' => 'Timestamp, when the user saw the post',
    'selectable' => false,
    'resolve' => function($post) {return object_get($post, 'pivot.seen_at');},
]

You can resolve it in a separate function resolveUserSeenAt($post) as well.
Hope it helps!

Thanks for getting back to me!

With this approach user_seen_at field will appear in GraphiQL when we have:

{
  users {
    has_posts {
      user_seen_at
    }
  }
}

However that means every posts query will also allow user_seen_at too:

{
  posts {
    user_seen_at
  }
}

The latter query will produce an error and null value. Is it possible to restrict user_seen_at field to only a has_posts context or is it something we have to compensate for using this approach?

You can make a subclass user_post that adds the user_seen_at field:

class UserPostType extends PostType {

    protected $attributes = [
        'name' => 'User post',
    ];

    public function fields()
    {
        return array_merge(parent::fields(), [
            'user_seen_at' => [
                'type' => Type::int(),
                'description' => 'Timestamp, when the user saw the post',
                'selectable' => false,
                'resolve' => function($post) {return object_get($post, 'pivot.seen_at');},
            ]
        ]);
    }

}

and the Query should return Type::listOf(GraphQL::type('user_post')).

Maybe there's a better way, but that's how I make subtypes that share multiple fields and it can also solve the pivot problem.

Cool, thanks for the suggestion 馃憤

This is awesome! Thx.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stevelacey picture stevelacey  路  8Comments

Artem-Schander picture Artem-Schander  路  7Comments

canhkieu picture canhkieu  路  3Comments

jglover picture jglover  路  6Comments

benjamin-ndc picture benjamin-ndc  路  3Comments