Eloquent Relationships

Just like in Laravel, you can define Eloquent Relationships in your schema.

Suppose you have defined the following model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Post extends Model
{
    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class);
    }
    
    public function author(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}

Just add fields to your type that are named just like the relationships:

type Post {
  author: User
  comments: [Comment!]
}

Because Laravel relationships can be accessed just like regular properties on your model, the default field resolver will work just fine.

Avoiding the N+1 performance problem

When accessing Eloquent relationships as properties, the relationship data is "lazy loaded". This means the relationship data is not actually loaded until you first access the property.

This leads to a common performance pitfall that comes with the nested nature of GraphQL queries: the so-called N+1 query problem. Learn more.

Lighthouse has got you covered with specialized directives that optimize the Queries for you.

One To One

Use the @hasOne directive to define a one-to-one relationship between two types in your schema.

type User {
  phone: Phone @hasOne
}

The inverse can be defined through the @belongsTo directive.

type Phone {
  user: User @belongsTo
}

One To Many

Use the @hasMany directive to define a one-to-many relationship.

type Post {
  comments: [Comment!]! @hasMany
}

Again, the inverse is defined with the @belongsTo directive.

type Comment {
  post: Post! @belongsTo
}

Many To Many

While many-to-many relationships are a bit more work to set up in Laravel, defining them in Lighthouse is a breeze. Use the @belongsToMany directive to define it.

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

The inverse works the same.

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

Renaming relations

When you define a relation, Lighthouse assumes that the field and the relationship method have the same name. If you need to name your field differently, you have to specify the name of the method.

type Post {
  author: User! @belongsTo(relation: "user")
}

This would work for the following model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Post extends Model 
{
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }
}