PHP
Adding Custom Logic and Attributes to Eloquent Many-to-Many Pivot Tables
Extend your many-to-many relationships by defining a custom pivot model, allowing you to add methods, accessors, and casts to your intermediate table.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;
// --- Custom Pivot Model (e.g., app/Models/ProjectUser.php) ---
class ProjectUser extends Pivot
{
// Define any custom casts for pivot attributes
protected $casts = [
'start_date' => 'datetime',
'is_active' => 'boolean'
];
// Add custom methods to the pivot model
public function isManager(): bool
{
return $this->role === 'manager';
}
public function scopeActive($query)
{
return $query->where('is_active', true);
}
}
// --- Main Models (e.g., app/Models/Project.php & app/Models/User.php) ---
class Project extends Model
{
public function users()
{
return $this->belongsToMany(User::class)
->using(ProjectUser::class) // Specify the custom pivot model
->withPivot('role', 'start_date', 'is_active') // Include extra columns
->withTimestamps();
}
}
class User extends Model
{
public function projects()
{
return $this->belongsToMany(Project::class)
->using(ProjectUser::class)
->withPivot('role', 'start_date', 'is_active')
->withTimestamps();
}
}
// --- Usage Example ---
$project = Project::find(1);
foreach ($project->users as $user) {
echo "User: " . $user->name . " (Role: " . $user->pivot->role . ")
";
if ($user->pivot->isManager()) {
echo " -> This user is a project manager.
";
}
echo " -> Started on: " . $user->pivot->start_date->format('Y-m-d') . "
";
if ($user->pivot->is_active) {
echo " -> Is an active member.
";
}
}
// Accessing pivot with a scope
$activeManagers = $project->users()->wherePivot('role', 'manager')->active()->get();
// Note: calling scopes directly on pivot via the relation requires 'wherePivot' or similar for the main query.
How it works: For many-to-many relationships where the intermediate (pivot) table holds additional data, Eloquent allows you to define a custom model for this pivot table. This snippet illustrates how to create a `ProjectUser` model that extends `Illuminate\Database\Eloquent\Relations\Pivot`. This custom pivot model enables you to add custom methods (like `isManager()`), define attribute casts (like `start_date`), and even scopes, making the pivot attributes behave like a full Eloquent model and simplifying interactions with the intermediate table data.