開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. PHP >
  4. Laravel >
  5. 【Laravel】Disctinctを使うとEloquentのBuilderでは、Paginatorのtotalが合わない

【Laravel】Disctinctを使うとEloquentのBuilderでは、Paginatorのtotalが合わない

こんにちは。
ニシザワです。

今回もLaravelの記事です。
タイトル通り、EloquentのBuilderでDistinct()ってやってしまうと、
paginatorのtotalが合わなくなってしまいます。
これは、Laravelのバグです。。。

今まで何回もPRが出てます↓↓
https://github.com/laravel/framework/pulls?q=is%3Apr+columns+getcountforpagination+is%3Aclosed
だが、却下され続けてます。
要するに、後方互換があるので、入れられないのです。

なので、Paginatorクラスから引っ張ってきて独自でPaginationを作ってみました。
下記がコード。
<?php
declare(strict_types=1);

namespace App\Services\Utility\Traits;
use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;


/**
 * Trait PaginatorTrait
 * @package App\Services\Utility\Traits
 */
trait PaginatorTrait{

    /**
     * @param Builder $builder
     * @param null $perPage
     * @param array $columns
     * @param string $pageName
     * @param null $page
     * @return LengthAwarePaginator
     */
    private function paginate(Builder $builder, $perPage = null, $columns = ['*'], $pageName = 'page', $page = null) : LengthAwarePaginator
    {
        $page = $page ?: Paginator::resolveCurrentPage($pageName);

        $perPage = $perPage ?: $builder->getModel()->getPerPage();

        $results = ($total = $builder->toBase()->getCountForPagination($columns))
            ? $builder->forPage($page, $perPage)->get($columns)
            : $builder->getModel()->newCollection();

        return Container::getInstance()->makeWith(LengthAwarePaginator::class, [
            'items' => $results,
            'total' => $total,
            'perPage' => $perPage,
            'options' => [
                'path' => Paginator::resolveCurrentPath(),
                'pageName' => $pageName,
            ],
        ]);
    }
}
要するに、Laravelが持っているPaginatorをそのまま持ってきて、必要な箇所を書き換えただけです。
使い方は下記
         $this->paginate($query,10 ,['tables.id']);
トレイトにしてあるので、そのまま必要なclassに読み込ましてあげれば使えます!!
第三引数にdistinctしたカラムを追加すれば大丈夫です。
TOPに戻る