korridor/laravel-has-many-merged
Adds a “hasManyMerged” Eloquent relationship to merge multiple hasMany relations into one, so you can query, eager load, paginate, and sort related models through a single unified relation—ideal for combining items from different sources or tables.
Start by installing the package via Composer:
composer require korridor/laravel-has-many-merged
Then, define merged relationships in your Eloquent models using the HasManyMerged trait and the mergedHasMany() method. For example, if a User has many posts and comments, you can merge them into a single activity relationship:
use Korridor\LaravelHasManyMerged\HasManyMerged;
class User extends Model
{
use HasManyMerged;
public function posts()
{
return $this->hasMany(Post::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function activity()
{
return $this->mergedHasMany([
'posts' => $this->posts(),
'comments' => $this->comments(),
], 'created_at', 'desc');
}
}
Your first use case will likely be loading a combined feed: User::with('activity')->get()->first()->activity.
Post and Comment instances).orderBy, where, and limit rules in one place instead of manually merging collections post-query:
$user->activity()->where('status', 'published')->limit(20)->get();
notes, logs, tasks) into activity, even when they don’t share a common table.with('activity') and eager-load constraints just like native relationships; the package handles merging logic at query time.public function scopeRecentActivity($query)
{
return $query->with(['activity' => fn($q) => $q->limit(10)]);
}
created_at, status, etc.). If they don’t, use selectRaw() or accessor mapping in the mergedHasMany() definition to homogenize fields.limit, where) before get().'created_at', 'desc') in mergedHasMany() applies globally; if relations have different column names (e.g., updated_at), alias columns in the relationship’s base queries:
$this->posts()->selectRaw('*, created_at as unified_timestamp')
paginate() on merged relations may produce incorrect offsets due to subquery merging. Prefer simplePaginate() or implement cursor-based pagination if exact counts aren’t required.How can I help you explore Laravel packages today?