Счетчик отношений Laravel OrderBy
Я пытаюсь получить самые популярные хакафоны, которые требуют упорядочения по соответствующему hackathon partipants->count()
. Извините, если это немного сложно понять.
У меня есть база данных со следующим форматом:
hackathons
id
name
...
hackathon_user
hackathon_id
user_id
users
id
name
Модель Hackathon
:
class Hackathon extends \Eloquent {
protected $fillable = ['name', 'begins', 'ends', 'description'];
protected $table = 'hackathons';
public function owner()
{
return $this->belongsToMany('User', 'hackathon_owner');
}
public function participants()
{
return $this->belongsToMany('User');
}
public function type()
{
return $this->belongsToMany('Type');
}
}
И HackathonParticipant
определяется как:
class HackathonParticipant extends \Eloquent {
protected $fillable = ['hackathon_id', 'user_id'];
protected $table = 'hackathon_user';
public function user()
{
return $this->belongsTo('User', 'user_id');
}
public function hackathon()
{
return $this->belongsTo('Hackathon', 'hackathon_id');
}
}
Я пробовал Hackathon::orderBy(HackathonParticipant::find($this->id)->count(), 'DESC')->take(5)->get());
, но я чувствую, что совершил большую ошибку (возможно, $this- > id), потому что он вообще не работает.
Как я могу попытаться получить самые популярные хакатоны, которые основаны на наибольшем числе связанных участников hackathonParticipants?
Ответы
Ответ 1
Изменение: Если вы используете Laravel 5.2 или выше, используйте kJamesy answer. Вероятно, он будет работать немного лучше, потому что не нужно будет загружать в память всех участников и хакатоны, только разбитые на страницы хакатоны и количество участников для этих хакатонов.
Вы должны быть в состоянии использовать методы Collection
sortBy()
и count()
, чтобы сделать это довольно легко.
$hackathons = Hackathon::with('participants')->get()->sortBy(function($hackathon)
{
return $hackathon->participants->count();
});
Ответ 2
Это работает для меня в Laravel 5.3, используя ваш пример:
Hackathon::withCount('participants')->orderBy('participants_count', 'desc')->paginate(10);
Таким образом, он упорядочен по запросу, а разбиение на страницы работает красиво.
Ответ 3
Другим подходом может быть использование withCount()
.
Hackathon::withCount('participants')
->orderBy('participants_count', 'desc')
->paginate(50);
Ссылка: https://laravel.com/docs/5.5/eloquent-relationships#querying-relations
Ответ 4
У меня была аналогичная проблема, и использование sortBy() не подходит из-за разбиения на страницы, как Сабрина Гелбарт прокомментировала предыдущее решение.
Поэтому я использовал db raw, здесь упрощенный запрос:
Tag::select(
array(
'*',
DB::raw('(SELECT count(*) FROM link_tag WHERE tag_id = id) as count_links'))
)->with('links')->orderBy('count_links','desc')->paginate(5);
Ответ 5
Вы также можете использовать оператор объединения. Как сказала Сабрина, вы не можете использовать sortby на уровне db.
$hackathons = Hackathon::leftJoin('hackathon_user','hackathon.id','=','hackathon_user.hackathon_id')
->selectRaw('hackathon.*, count(hackathon_user.hackathon_id) AS `count`')
->groupBy('hackathon.id')
->orderBy('count','DESC')
->paginate(5);
Но этот код берет все записи из базы данных. Поэтому вы должны разбивать на страницы вручную.
$hackathons = Hackathon::leftJoin('hackathon_user','hackathon.id','=','hackathon_user.hackathon_id')
->selectRaw('hackathon.*, count(hackathon_user.hackathon_id) AS `count`')
->groupBy('hackathon.id')
->orderBy('count','DESC')
->skip(0)->take(5)->get();
Рефералы: fooobar.com/info/311137/...