$ lexprog.com

// notes from an old coder -- php, databases, and the occasional rant

[September 30, 2025] Eloquent ORM

Eloquent Pivot Tables: Extra Columns

Eloquent Pivot Tables: Extra Columns

────────────────────────────────────────────────────────

Eloquent Pivot Tables: Extra Columns

Tip: Access Pivot Data

public function roles(): BelongsToMany
{
    return $this->belongsToMany(Role::class)->withPivot('expires_at');
}

Gotcha: withTimestamps()

return $this->belongsToMany(Role::class)->withTimestamps();

Adds created_at and updated_at to the pivot table.

Tip: Custom Pivot Model

class RoleAssignment extends Pivot
{
    protected $table = 'role_user';
}

Gotcha: Attach with Data

$user->roles()->attach($roleId, ['expires_at' => now()->addYear()]);

Tip: Sync with Data

$user->roles()->sync([
    1 => ['expires_at' => now()->addYear()],
    2 => ['expires_at' => now()->addMonth()],
]);

Gotcha: using() for Custom Pivot

return $this->belongsToMany(Role::class)->using(RoleAssignment::class);

Tip: Use cursor() for Memory-Neutral Iteration

When exporting 100K rows, get() loads everything into memory. cursor() uses yield and keeps memory flat regardless of row count. Perfect for artisan commands.

Tip: whereHas() vs load() — Two Different Things

whereHas() filters the parent query by relationship existence. load() eager-loads relationships AFTER the query. Mixing them up is a common source of logic bugs.

Gotcha: withCount() Adds a Subquery

withCount('comments') runs a correlated subquery on every row. On large tables, this can be slower than a separate query. Profile before relying on it.

Senior Insight

I've learned to be suspicious of Eloquent 'magic' methods and conventions. $user->posts looks like a property access but executes a database query. $user->delete() looks harmless but cascades through relationships. The magic is convenient but makes the side effects invisible. I document non-obvious Eloquent behavior in code comments and prefer explicit method calls over implicit property access in complex code paths.

Source: Laravel Docs (https://laravel.com/docs/eloquent), Laravel News (https://laravel-news.com/), Freek.dev (https://freek.dev/tags/eloquent)

────────────────────────────────────────────────────────
<-- back to posts