Laravel Eloquent Just Got Smarter: HasManyThrough + Pipe Operator + Auto-Cleanup with Rector

Laravel devs love expressive syntax—and Laravel 12 just made it even cleaner. In this post, we’ll explore two powerful tools for writing elegant, maintainable Eloquent code:

  • HasManyThrough for deep relationships
  • The new pipe operator (->) for fluent chaining
  • Bonus: how to automate cleanups with Rector rules

Whether you’re building a multi-tenant SaaS or just tired of messy relationship logic, this combo will upgrade your Laravel game.


🔗 HasManyThrough: The Underrated Power Move

Let’s say you have:

  • Country → has many Users
  • User → has many Posts
  • You want: Country → has many Posts (through Users)

Instead of nested loops or joins, use:

class Country extends Model
{
    public function posts(): HasManyThrough
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}

Why it matters:

  • ✅ One-liner relationship
  • ✅ Optimized SQL joins
  • ✅ Works with eager loading, constraints, and pagination

Pro tip: You can chain constraints like:

$country->posts()->where('published', true)->latest()->get();

🧪 Pipe Operator: Laravel 12’s Fluent Secret

Laravel 12 introduces the pipe operator (->) for chaining transformations:

$posts = $country->posts()
    ->get()
    ->pipe(fn($collection) => $collection->filter(fn($post) => $post->isFeatured()));

It’s like tap() but for transforming values—not just side effects.

Use cases:

  • ✅ Clean up post-query logic
  • ✅ Replace nested callbacks
  • ✅ Make your code read top-down

🛠️ Automate Clean Code with Rector

Rector Laravel is a tool that refactors your codebase automatically. Want to convert old abort() logic to abort_if()? Done. Want to enforce default values or modern syntax? Easy.

Example rule:

// Before
if (!$user) {
    abort(404);
}

// After
abort_unless($user, 404);

Recommended rules for Eloquent cleanup:

  • AbortIfRector
  • AddArgumentDefaultValueRector
  • SimplifyIfReturnBoolRector
  • Custom rules for relationship naming and query constraints

🧠 Real-World Use Case: Multi-Tenant Blog Platform

Imagine you’re building a blog platform where:

  • Organization → has many Users
  • User → has many Posts
  • You want: Organization → has many Posts

Use HasManyThrough:

class Organization extends Model
{
    public function posts(): HasManyThrough
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}

Then filter with pipes:

$org->posts()
    ->latest()
    ->get()
    ->pipe(fn($posts) => $posts->filter(fn($p) => $p->isPublic()));

Clean, readable, and scalable.


✅ Final Thoughts

Laravel 12’s pipe operator + Eloquent’s HasManyThrough = expressive, modern relationship logic. Add Rector to the mix, and you’ve got a clean code pipeline that scales.

If you’re building SaaS, dashboards, or multi-tenant apps—this trio is your secret weapon.


References (3)

1Illuminate\Database\Eloquent\Relations\HasManyThrough | Laravel API. https://api.laravel.com/docs/8.x/Illuminate/Database/Eloquent/Relations/HasManyThrough.html

2rector-laravel/docs/rector_rules_overview.md at main – GitHub. https://github.com/driftingly/rector-laravel/blob/main/docs/rector_rules_overview.md

3Laravel Has Many Through Eloquent Relationship Tutorial. https://www.itsolutionstuff.com/post/laravel-has-many-through-eloquent-relationship-tutorialexample.html

Leave a Reply

Your email address will not be published. Required fields are marked *