Just like in Laravel, you can define Eloquent Relationships in your schema.
Suppose you have defined the following model:
<?php
namespace App\Models;
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.
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.
When you decorate your relationship fields with Lighthouse's built-in relationship directives, queries are automatically combined through a technique called batch loading. That means you get fewer database requests and better performance without doing much work.
Batch loading might not provide ideal performance for all use cases. You can turn it off by setting the config option
batchload_relations
tofalse
.
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
}
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
}
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
}
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\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Post extends Model
{
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}