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?
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.
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 typeType::listOf(GraphQL::type('post')). The PostType should then have the following field:You can resolve it in a separate function
resolveUserSeenAt($post)as well.Hope it helps!