Skip to content

Instantly share code, notes, and snippets.

@Sairahcaz
Created July 6, 2026 12:29
Show Gist options
  • Select an option

  • Save Sairahcaz/5cb8b37d216dd34d957fb0f038ee783e to your computer and use it in GitHub Desktop.

Select an option

Save Sairahcaz/5cb8b37d216dd34d957fb0f038ee783e to your computer and use it in GitHub Desktop.
Eloquent & Laravel Best Practices

Eloquent & Laravel Best Practices

Prefer Laravel's expressive, model-aware APIs over manual ID plumbing. Passing models instead of raw IDs is safer (correct key resolution, route model binding) and reads better. Each section shows the pattern to avoid and the one to use.

Routing

Pass the model itself to route(), not its key. Laravel resolves thea route key automatically (and respects custom route keys).

// Avoid
route('users.show', $user->id);

// Prefer
route('users.show', $user);

Creating Related Models

Create through the relationship instead of setting the foreign key by hand.

// Avoid
Post::create(['user_id' => $user->id, ...$attributes]);

// Prefer
$user->posts()->create($attributes);

BelongsToMany / Pivot

attach() and updateExistingPivot() accept models directly.

// Avoid
$user->roles()->attach($role->id);

// Prefer
$user->roles()->attach($role);
// Avoid
$user->roles()->where('roles.id', $role->id)->update([...]);

// Prefer
$user->roles()->updateExistingPivot($role, [...]);

Querying by Relationship

Use whereBelongsTo() and whereKey() instead of hand-written foreign key or primary key clauses.

// Avoid
Post::where('user_id', $user->id)->get();

// Prefer
Post::whereBelongsTo($user)->get();
// Avoid
$user->posts()->where('id', $post->id)->exists();

// Prefer
$user->posts()->whereKey($post)->exists();

Comparing Models

Use is() (and isNot()) to compare related models instead of comparing IDs.

// Avoid
if ($post->user_id === $user->id) {
    // ...
}

// Prefer
if ($post->user()->is($user)) {
    // ...
}

Associating BelongsTo Relations

Use associate() instead of writing the foreign key directly.

// Avoid
$post->update(['user_id' => $user->id]);

// Prefer
$post->user()->associate($user)->save();

Timestamp Columns

Use touch() to set a timestamp column to now.

// Avoid
$project->update(['cancelled_at' => now()]);

// Prefer
$project->touch('cancelled_at');

Authorization Guards

Use Gate::allowIf() / Gate::denyIf() for inline authorization checks instead of manual abort(403).

// Avoid
if (! $admin) {
    abort(403);
}

// Prefer
Gate::allowIf($admin);
@anikwai

anikwai commented Jul 6, 2026

Copy link
Copy Markdown

Nice

@altayevrim

altayevrim commented Jul 7, 2026

Copy link
Copy Markdown

Well these are nice but probably I'd stick with this.

$project->update(['cancelled_at' => now()]);

First, I like to write it like this, and well I like to read it like this. Ofc probably everyone who knows how to read code also knows what does touch means but, this way seems more cleaner.

@Sairahcaz

Copy link
Copy Markdown
Author

@jasonmccreary

Copy link
Copy Markdown

Like them, although I probably wouldn't adopt "Comparing Models". Namely because is and isNot check more than the ID. Not sure I'd trade a straightforward language comparison for a method call that compares more underneath. Nitpicky, but different.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment