Skip to content

Instantly share code, notes, and snippets.

@boukeversteegh
Last active April 21, 2017 13:45
Show Gist options
  • Save boukeversteegh/50c138578c9ca4b9282491b274db5d16 to your computer and use it in GitHub Desktop.
Save boukeversteegh/50c138578c9ca4b9282491b274db5d16 to your computer and use it in GitHub Desktop.
Sorting Laravel model by relationship count (see comments for usage)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* Class BaseModel
* @package App
*/
abstract class BaseModel extends Model
{
/**
* @param $query
* @param $relationName
* @param string $alias
*/
public function scopeIncludeCount($query, $relationName, $alias = null)
{
$alias = $alias ?: $relationName . 'Count';
$relation = call_user_func([$this, $relationName]);
/**
* @var HasMany|BelongsToMany $relation
*/
$relation->getRelated()->getTable();
$related = $relation->getRelated();
if ($relation instanceof HasMany) {
$relationTable = $related->getTable();
$query
->leftJoin($relationTable, $relation->getForeignKey(), '=', $relation->getQualifiedParentKeyName())
->groupBy($this->getTable() . '.' . $this->primaryKey)
->addSelect([
$this->getTable() . '.*',
\DB::raw(sprintf('COUNT(DISTINCT %s.%s) as %s', $related->getTable(), $related->primaryKey, $alias))]
);
} else {
$relationTable = $relation->getTable();
$query
->leftJoin($relationTable, $relation->getForeignKey(), '=', $relation->getQualifiedParentKeyName())
->groupBy($relation->getQualifiedParentKeyName())
->addSelect([
$this->getTable() . '.*',
\DB::raw(sprintf('COUNT(DISTINCT %s) as %s', $relation->getOtherKey(), $alias))
]
);
}
}
}
@boukeversteegh
Copy link
Author

Above scope allows you to sort your models (in database) by relationship count. It works by performing a JOIN on the related model.

class User extends BaseModel {
    public function posts() {
        return $this->hasMany(Post::class);
    }
}

$query= User::query();
$query->includeCount('posts', 'postCount');
$query->orderBy('postCount', 'DESC');

$users = $query->get();

// On $user you can also do $user->postCount;

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