I’m trying to paginate the relations through a parent pivot.
A user has topics and a topic can have multiple users. Multiple users can be the owner of a topic. A topic has messages.
class Topic extends Model
{
//Casts Fillables etc.
public function user(): BelongsToMany
{
return $this->belongsToMany(User::class, 'topic_users', 'topic_uuid', 'user_uuid')
->withPivot([
'uuid',
'user_uuid',
'is_owner',
'created_at',
'updated_at',
])
->using(User::class);
}
public function messages(): HasMany
{
return $this->hasMany(Message::class, 'topic_uuid', 'uuid');
}
}
class User extends Authenticatable
{
//Casts Fillables etc
public function topics(): BelongsToMany
{
return $this->belongsToMany(Topic::class, 'topic_users')
->withPivot(
'uuid',
'is_owner',
'created_at',
'updated_at'
);
}
}
TopicType
namespace AppGraphQLTypes;
use AppModelsTopic;
use GraphQLTypeDefinitionType;
use RebingGraphQLSupportFacadesGraphQL;
use RebingGraphQLSupportType as GraphQLType;
class TopicType extends GraphQLType
{
protected $attributes = [
'name' => 'Topic',
'description' => 'The topic and it's messages',
'model' => Topic::class,
];
public function resolveMessagesField($root, $args) {
return $root->messages()->paginate($args['limit'], ['*'], 'page', $args['page']);
}
public function fields(): array
{
return [
'uuid' => [
'type' => Type::string(),
'description' => 'The UUID of the Topic',
],
'title' => [
'type' => Type::string(),
'description' => 'The title of the Topic',
],
'slug' => [
'type' => Type::string(),
'description' => 'The slug of the Topic',
],
'key' => [
'type' => Type::string(),
'description' => 'The unique key that identifies the topic',
],
'last_message_at' => [
'type' => Type::string(),
'description' => 'UTC Timestamp of when the last message has been send',
],
'last_message' => [
'type' => Type::nonNull(GraphQL::type('Message')),
'description' => 'The last message that has been sent in this topic',
],
'messages' => [
'type' => GraphQL::paginate('Message'),
'description' => 'The messages in this topic',
'args' => [
'limit' => [
'name' => 'limit',
'type' => Type::int(),
'rules' => ['required', 'numeric', 'min:1', 'max:20'],
],
'page' => [
'name' => 'page',
'type' => Type::int(),
],
]
]
];
}
}
Message Type
namespace AppGraphQLTypes;
use AppModelsMessage;
use GraphQLTypeDefinitionType;
use RebingGraphQLSupportFacadesGraphQL;
use RebingGraphQLSupportType as GraphQLType;
class MessageType extends GraphQLType
{
protected $attributes = [
'name' => 'Message',
'description' => 'Represents the message type',
'model' => Message::class
];
public function fields(): array
{
return [
'uuid' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The UUID of the message',
],
'topic_uuid' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The UUID of the Topic',
],
'title' => [
'type' => Type::string(),
'description' => 'Message Title',
],
'message' => [
'type' => Type::string(),
'description' => 'The actual message',
],
'received_at' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The timestamp the server has received the message',
],
'processed_at' => [
'type' => Type::string(),
'description' => 'The timestamp the server was done processing the message',
],
];
}
}
TopicQuery
<?php
declare(strict_types=1);
namespace AppGraphQLQueries;
use AppGraphQLHelpersGraphQLHelpers;
use AppModelsTopic;
use Closure;
use GraphQLTypeDefinitionResolveInfo;
use GraphQLTypeDefinitionType;
use IlluminateSupportFacadesAuth;
use RebingGraphQLSupportFacadesGraphQL;
use RebingGraphQLSupportQuery;
class TopicQuery extends Query
{
protected $attributes = [
'name' => 'topic',
'description' => 'A query to fetch the topic and the last 25 messages',
];
public function type(): Type
{
return GraphQL::type( 'Topic');
}
public function args(): array
{
return [
'uuid' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The UUID of the Topic',
],
'limit' => [
'type' => Type::int(),
'defaultValue' => GraphQLHelpers::DEFAULT_PAGE_SIZE,
'description' => 'The amount of items you want to fetch',
'rules' => ['max:50'],
],
'page' => [
'type' => Type::int(),
'defaultValue' => GraphQLHelpers::DEFAULT_PAGE_NUMBER,
],
];
}
public function resolve($root, array $args, $context, ResolveInfo $resolveInfo, Closure $getSelectFields)
{
$fields = $getSelectFields();
return= Topic::query()->whereHas('user', function ($query) {
return $query->where('user_uuid', '=', Auth::guard('graphql')->user()->uuid);
})
->where('uuid', $args['uuid'])
->select($fields->getSelect())
->with('messages')
->paginate($args['limit'], ['*'], 'page', $args['page']);
}
}
The query I’m trying to achieve:
{
topic(uuid: "7ca8af62-8bb5-4013-9141-82483fea06fa") {
uuid
title
messages(limit: 2, page: 1) {
data {
uuid
}
}
}
}
The args are passed correctly
I still get the 10 first messages, while the topic itself is correctly fetched.