Laravelにおけるdistinctありのページネーションでの総件数の求め方

Laravelのページネーションでdistinctを使うと総ヒット件数が正しく計算されない。
自分はLaravel 5.2で経験したが、最新のバージョンだと修正されているかもしれない(が調べたところ5.4ではおかしいらしい)(いや、修正されたのか??)。

https://stackoverflow.com/questions/41283083/distinct-with-pagination-in-laravel-5-2-not-working
https://github.com/laravel/framework/issues/21242

distinctを使わなければいいのだが、そうはいかない場合もある。
そこで対応したのが以下の方法(5.2を想定)。
例だとdistinctを使う意味がないと思うがそこは複雑なSQLを脳内補完してほしい。

DB::enableQueryLog();

$page    = 2;
$limit   = 20;
$builder = User::select('id', 'name')->distinct()->orderBy('id', 'desc');
$users   = $builder->skip(($page - 1) * $limit)->take($limit)->get();

// totalの計算
$queries     = DB::getQueryLog();
$last_query  = end($queries);
$total_query = preg_replace('/\sorder\sby.+?$/', '', $last_query['query']);
$total       = DB::select(DB::raw('select count(*) as total from (' . $total_query . ') tmp_users'), $last_query['bindings']);

DB::disableQueryLog();

クエリーログを有効化して、最後に実行したSQLを取得する。
$last_query['query']にそのSQLが格納されているのだが、そこには

select distinct `id`, `name` from `users` order by `id` desc limit 20 offset 20

が入っていて、これだと総件数は求められない。
そこで正規表現でorder by以下を削除する。

select distinct `id`, `name` from `users`

これをselect count(*)することでdistinctでも正しい総件数が得られるようになる。
以上:pray_tone2:

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.