Understanding Relationships
Eloquent makes working with database relationships elegant and intuitive. Let's explore the different types of relationships available.
One-to-Many Relationships
The most common relationship type. A user has many posts, a post belongs to a user.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class User extends Model
{
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
}
class Post extends Model
{
public function author(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}
Many-to-Many with Pivot Data
When you need additional data on the pivot table:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class User extends Model
{
public function roles(): BelongsToMany
{
return $this->belongsToMany(Role::class)
->withPivot(['assigned_at', 'assigned_by'])
->withTimestamps()
->using(RoleUser::class);
}
public function assignRole(Role $role, User $assigner): void
{
$this->roles()->attach($role->id, [
'assigned_at' => now(),
'assigned_by' => $assigner->id,
]);
}
}
Polymorphic Relationships
When multiple models can have the same relationship:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class Comment extends Model
{
public function commentable(): MorphTo
{
return $this->morphTo();
}
}
class Post extends Model
{
public function comments(): MorphMany
{
return $this->morphMany(Comment::class, 'commentable');
}
}
class Video extends Model
{
public function comments(): MorphMany
{
return $this->morphMany(Comment::class, 'commentable');
}
}
Eager Loading
Avoid the N+1 query problem with eager loading:
<?php
// Bad - N+1 problem (101 queries for 100 posts)
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name;
}
// Good - Eager loading (2 queries)
$posts = Post::with('author')->get();
foreach ($posts as $post) {
echo $post->author->name;
}
// Nested eager loading
$posts = Post::with([
'author',
'comments.user',
'tags',
])->get();
// Constrained eager loading
$posts = Post::with([
'comments' => function ($query) {
$query->where('approved', true)
->latest()
->limit(5);
},
])->get();
Conclusion
Understanding relationships deeply will make you a more effective Laravel developer. Always use eager loading to prevent N+1 queries, and leverage pivot tables for complex many-to-many relationships.