質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.78%

Laravel solarium ページネーション ページ遷移先にデータが表示されない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,096

score 59

solariumのpaginationを実現したい

solrの全文検索システムを作っています。
ページネーション機能を実装中にページ遷移先にデータが参照されませんでした。

pagination実装ソースコード(Laravelのカスタムページネータを使用)修正前

SearchController.php

//クエリ
$query = $this->client->createSelect();
$query->setQuery($request['keyword']);

//クエリの結果を取得
$resultset = $this->client->select($query);


//ページネーション
$perPage = $query->getRows();  //defalutの10件
$startPage = $query->getStart(); //defalutの0件

// Illuminate\Pagination\LengthAwarePaginator を使用し、カスタムページネータを作成

//カスタムページネータ
    $perPage = 10; 
    $startPage = $query->getStart(); //0

// ページ番号
    $page = max(0, Paginator::resolveCurrentPage() - 1);

    $paginator=NULL;
    foreach ($resultset as $document) {

        // ページ内の要素を取得
        $sliced = array_slice((array)$document->id, $page  * $perPage, $perPage);


        // ページネータインスタンス生成
        $paginator = new LengthAwarePaginator(
            $sliced,
            $resultset_total,//$resultset_total = $resultset->getNumFound();
            $perPage,
            null,
            [
                'page' => $page,
                'path' => Paginator::resolveCurrentPath(),
            ]

        );

    }

修正後↓(解決)

SearchController.php


$query = $this->client->createSelect();
$query->setQuery($request['keyword']);

$perPage = $query->getRows();  //defalutの10件
$startPage = $query->getStart(); //defalutの0件


    $page = max(0, Paginator::resolveCurrentPage()); //-1を削除

   // 配列のoffset位置からperPage分の配列を切り抜く
   $offset = ( $page * $perPage ) - $perPage;

   $sliced = $query->setStart($offset)->setRows($perPage);
   dump($sliced);

  //結果
  $resultset = $this->client->select($query);

//結果を全件取得
        $resultset_total = $resultset->getNumFound();

        $paginator = new LengthAwarePaginator(
            $sliced,
            $resultset_total,
            $perPage,
            $page,  
            [
                'page' => $page,
                'path' => Paginator::resolveCurrentPath(),
                'query' => ['keyword' => $request['keyword']],

            ]

        );
search.blade.php

<ul>
    <li>{{ $paginator }}</li>
</ul>


ページネーションはブラウザに表示されているが
2ページ目を押下するとURLはhttp://xxx.x.x.x/list?keyword=〇〇&page=2となりますが
結果は表示されない。
(1ページ目に全件表示されている)

試したこと

https://stackoverflow.com/questions/17501630/how-do-you-paginate-in-solr-using-solarium
上記を参考にし、下記のようなlimitをつけて参照するようにする → 結果変わらず

$query->setStart(0)->setRows(20);

バージョン

Laravel5.4
solarium 3.8
solr 5.5.4

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

追記:すいません、別の解答欄に書いてしまいました…

なるほどです。

solrとsolariumは使ったことがなかったので、少し調査してみました。
どうやら、setStart()とsetRows()を使うことで、何番目から何件とってくるか指定できるのですね。(array_sliceと同じこと)

でしたら、array_sliceは不要かもしれませんね
何度も試してもらって申し訳ないですが、client->selectしているところと
array_sliceの文をコメントアウトし、offsetの計算文の下に以下を追加してみてください。

$query->setStart($offset)->setRows($perPage);

ページが進むにつれて、取得する開始位置(offset)をずらしていくといいのかなと。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/13 18:26

    > solrとsolariumは使ったことがなかったので、少し調査してみました
    すみません。わざわざ調査してくださりありがとうございます。
    修正後のソースを更新しました。
    確認したところ、setStart()が次ページへ行くと変更されました!
    ありがとうございます。

    > array_sliceと同じこと
    勉強不足で同じことだとは気づけませんでした。
    ありがとうございます。

    検索するにあたってクエリを
    $query = $this->client->createSelect();
    $query->setQuery($request['keyword']);
    と、最初で投げているのですが、ここが次ページの遷移先でNULLになってしまい参照されていないようでした。。
    ここができれば解決できそうです。
    もう少しお力をお借りできませんでしょうか。。
    大変申し訳ございませんがよろしくお願いします。

    キャンセル

  • 2017/06/13 19:27

    いえいえ。自分も勉強になっていますのでお気になさらずに

    自分で環境を作ってみて試しました(笑
    都道府県のテストデータで試したので若干異なりますが、
    ソースを載せてみます。

    /* 都道府県市町村を取得するやつ
    public function towncode(Request $request)
    {
    $query = $this->client->createSelect();
    $query->setQuery("todouhuken:".$request['keyword']);


    $perPage = $query->getRows(); //defalutの10件
    $page = max(0, Paginator::resolveCurrentPage());

    $offset = ( $page * $perPage ) - $perPage;

    $query->setStart($offset)->setRows($perPage);
    $resultset = $this->client->select($query);

    // ここ重要。getNumFoundでHitした全件数を取得
    // count($resultset)だと10件なのでページングしない
    $resultset_total = $resultset->getNumFound();

    $paginator = new LengthAwarePaginator(
    $resultset,
    $resultset_total,
    $perPage,
    $page,
    [
    'path' => Paginator::resolveCurrentPath(),
    'query' => ['keyword' => $request['keyword']], // こうするとページリンクにkeywordクエリーが引き継がれる
    ]
    );

    return view('towncode', ['paginator' => $paginator]);
    }


    -- towncode.blade.php

    <!doctype html>
    <html lang="{{ config('app.locale') }}">
    <head>
    <meta charset="utf-8">
    <!-- Fonts -->
    <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
    <!-- Bootstrap-->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha256-KXn5puMvxCw+dAYznun+drMdG1IFl3agK0p/pqT9KAo= sha512-2e8qq0ETcfWRI4HJBzQiA3UoyFk6tbNyG+qSaIBZLyW9Xf3sWZHN/lxe9fTh1U45DpPf07yj94KsUHHWe4Yk1A=="crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/cosmo/bootstrap.min.css" integrity="sha384-h21C2fcDk/eFsW9sC9h0dhokq5pDinLNklTKoxIZRUn3+hvmgQSffLLQ4G4l2eEr" crossorigin="anonymous">
    </head>
    <body>
    <div class="container">
    <ul>
    @foreach ($paginator->items() as $item)
    <li>{{ $item->todouhuken }}: {{ $item->shichouson }}</li>
    @endforeach
    </ul>
    </div>
    {{ $paginator }}
    </body>
    </html>

    見にくいですが、参考にしてみてください。

    キャンセル

  • 2017/06/13 19:53

    > 自分で環境を作ってみて試しました(笑
    おっしゃっていただいたように修正後クエリを引き継ぐことができました。
    とても助かりました!長々とお付き合いいただきまして本当にありがとうございました。
    私一人では解決できませんでした。

    ページネーションが行えた修正のソース更新しました。

    本当にありがとうございました。

    キャンセル

  • 2017/06/13 19:56

    解決されたようでよかったです!
    こちらこそ勉強になりました。

    キャンセル

0

こんにちは

LengthAwarePaginatorのドキュメントを見てみますと
constractの第4引数(nullが設定されているところ)は、
現在ページ数を指定するようになっていますので、$pageを指定してみるといいのかなと思います。

ご参考にしてみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/12 19:11

    いえいえ。ご回答いただけるだけでも嬉しく思います。
    ありがとうございます。

    > あと、質問欄のソースを修正後ソースに更新してもらうと助かります。
    こちら、大変失礼しました。
    修正後ソースを追加いたしました。ご確認を宜しくお願い致します。

    キャンセル

  • 2017/06/13 10:13

    修正ソースありがとうございます。

    すいません。
    一点、間違ったことを言ってました。!
    LengthAwarePaginatorの第一引数は、表示させる分のみ指定するようです。全配列と言ってました。すいません。

    以下のソースようにするとどうでしょうか?

    // -1を削除してます
    $page = max(0, Paginator::resolveCurrentPage());

    // 配列のoffset位置からperPage分の配列を切り抜く
    $offset = ( $page * $perPage ) - $perPage;
    $sliced = array_slice($resultset, $offset, $perPage, true);

    $paginator = new LengthAwarePaginator(
    $sliced,
    $resultset_total,
    $perPage,
    $page, //NULLから$pageへ変更
    [
    'page' => $page,
    'path' => Paginator::resolveCurrentPath(),
    ]
    );

    キャンセル

  • 2017/06/13 14:02

    > LengthAwarePaginatorの第一引数は、表示させる分のみ指定するようです。全配列と言ってました。すいません。
    いえ!勉強になりました。ありがとうございます。

    修正後のソースを編集させていただきました。
    確認したところ、dump($offset);では期待する数値を確認取れました!
    ありがとうございます。(次ページに遷移した時に次の件数の値が表示されています)
    現時点は1ページ目に全件のsolrの結果が参照されています。
    solrから参照する件数の設定に問題がありそうです。。。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る