Search code examples
laravelgraphqlpivot-tablelaravel-lighthouse

Laravel Lighthouse GraphQL query data from a pivot table that connects three tables


In Laravel Lighthouse GraphQL, how can you retrieve the information from an intermediate "pivot" table?

Suppose I have Users and Roles in a belongsToMany relation:

type User {
  roles: [Role!]! @belongsToMany
}

type Role {
  users: [User!]! @belongsToMany
}

type Query {
    user(id: ID! @eq): User @find
    role(id: ID! @eq): Role @find
}

And also suppose that the intermediate table User_Role contains columns "created_at" and "tag_id".
How would I go about to include the "created_at" in my query?
How would I get the tag that the tag_id refers to?


Solution

  • I found out that you can do it like this:

    First, make sure that the relation in the User model calls ->withPivot('created_at', 'tag_id'):

    class User extends Model {
        public function roles(): BelongsToMany
        {
            return $this->belongsToMany(\App\Models\Role::class, 'User_Role')
                        ->using(User_Role::class) // only needed to retrieve the tag from the tag_id
                        ->withPivot('created_at', 'tag_id');
        } 
    }
    

    Create a class for the intermediate table that extends Pivot:

    class User_Role extends Pivot
    {
        public function tag(): BelongsTo
        {
            return $this->belongsTo(\App\Models\Tag::class, 'tag_id');
        }
    }
    

    Now change the GraphQL code as follows:

    type User {
        id: ID!
        roles: [Role!] @belongsToMany
    }
    
    type Role {
        id: ID!
        pivot: UserRolePivot # this is where the magic happens
    }
    
    type UserRolePivot {
        created_at: Date!
        tag: Tag! @belongsTo
    }
    
    type Tag {
        id: ID!
        name: String!
    }
    

    And now you can query like this:

    {
      users {
        id
        roles {
          id
          pivot {
            created_at
            tag {
              id
              name
            }
          }
        }
      }
    }