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

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

ただいまの
回答率

90.52%

  • PHP

    23494questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP3のPaginator機能を使用した上で、検索条件がGETパラメータなどで見えないようにPOSTでの実装方法を教えていただきたいです。

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 126

hikaru1013

score 0

PHP(CakePHP3.7.1)で商品の画像管理システムを作っています。
現在CakePHP3のPaginator機能を使用し商品画像一覧と検索機能を実装しているのですが、検索条件がGETパラメータで見えてしまう状態です。
今後アカウント管理機能も作成する予定で、メールアドレスなど個人情報が検索条件に含めれる想定なので、CakePHP3のPaginator機能を使用した上でGETパラメータなどで検索条件が見えない形で、検索を行った後に2ページ目に遷移しても検索条件が引き継がれたままで検索条件に該当するデータの2ページ目が正常に表示される実装方法を教えていただきたいです。

該当のソースコード

Template

<?= $this->Form->create(null, ['type'=>'get', 'url'=>['action'=>'index', $producttypeId]]) ?>
    <!-- 検索 -->
    <h4 class="function-name-color">・画像検索</h4>
    <div class="form-group input-group">
        <span class="input-group-addon">キーワード</span>
        <?= $this->Form->input('keyword', ['type'=>'text', 'label'=>false, 'placeholder'=>'キーワード入力してください', 'class'=>'form-control', 'value'=>$keyword]) ?>
        <span class="input-group-addon">商品カテゴリ</span>
        <?= $this->Form->input('category_id', [
            'label'=>false,
            'options'=>$categories,
            'class'=>'form-control',
            'templates' => ['inputContainer' => '{{content}}'],
            'empty'=>'全てのカテゴリ',
            'default'=>$categoryId,
        ]) ?>
    </div>
    <div class="text-center" style="margin-bottom:23px;">
        <?= $this->Form->button(__('検索<i class="ti-search m-l-5"></i>'), ['id'=>'button', 
         'type'=>'submit', 'class'=>'btn btn-info p-l-20 p-r-20', 'div'=>false,'role'=>'button']) ?>
    </div>
<?= $this->Form->end() ?>

Controller

/**
 * Index method
 * 初期表示・検索結果表示
 */
public function index($producttypeId = null)
{
    $this->loadModel('Categories');
    $this->loadModel('Producttypes');
    // 検索条件
    $keyword = null;
    $categoryId = null;
    // 画像データ
    $materialData = null;

    if ($this->request->is('get')) {
        // 検索ファイル名
        $keyword = $this->request->query('keyword');
        // 検索カテゴリ
        $categoryId = $this->request->query('category_id');
    }

    // 商品カテゴリプルダウンデータ取得
    $categories = $this->Categories->find('list')->where(['producttype_id' => $producttypeId]);

    // 検索条件追加
    $where_tmp = [];
  if ($keyword) {
        $where_tmp += ['OR' => [
            'Items.name like' => '%'. $keyword. '%',
            'Items.description like' => '%'. $keyword. '%']
        ];
  }

  if ($categoryId) {
    $where_tmp += ['Items.category_id' => $categoryId];
   }

   // CakePHPページング機能
   $this->paginate = [
        'contain'=>['Categories'],
        'conditions'=>['Categories.producttype_id' => $producttypeId, $where_tmp],
        'order' => ['Items.id DESC'],
        'limit'=>30,
    ];

    $materialData = $this->paginate($this->Items);

    $this->set(compact('producttypeId', 'categories', 'materialData', 'keyword', 'categoryId'));
}

試したこと

GETではなくPOSTで実装してみたのですが、検索条件を入力し検索結果一覧表示後に2ページ目に遷移すると、検索条件がリセットされてしまい、検索をかけていない全件表示状態の2ページ目が表示されてしまいました。
その為、検索条件がPOSTされた際に検索条件をsessionで保持し、2ページ目に遷移した時にsessionに保持されている条件でデータ抽出するようにしてみたのですが、sessionに検索条件が保持されている場合は無条件に検索をかけてしまうため、メニューから「商品の画像管理システム」のリンクを押下した時の初期表示のときも、sessionに検索条件が保持されている場合は検索をかけてしまう動きとなってしまいます。
初期表示の時はsessionに保持さている検索条件を破棄しようとしたのですが、メニューのリンクが押下された時の初期表示なのかPaginator機能の進むや戻るのリンクが押下された時の表示なのかがController側で識別ができず、POSTでsessionを使用しての検索条件を保持する実装は断念しました。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+1

今後アカウント管理機能も作成する予定で、メールアドレスなど個人情報が検索条件に含めれる想定なので、

  • 検索条件をすべてフォームから指定するのであれば、それは見えて構わない情報です。
  • 「ユーザーに見せない検索条件を追加する」のであれば、それはサーバサイドで処理してしまって、クライアント側には一切関係させないのが適切です。

ということで、「検索条件をPOSTで伝える」という解決策自体が、この課題への対応手段としてはあまり適切でないかなと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/10 12:54

    そして、POSTするにしても、ブラウザ内の検証ツールなどを使えば簡単に見られますので、情報の秘匿にはなりません。

    キャンセル

  • 2019/04/10 15:07 編集

    個人的にですが、アカウント検索後にメールアドレスなどの個人的情報がGETパラメータにのったままのURLが履歴などで残ってしまうので気になってしまうので「検索条件をPOSTで伝える」以外の方法も含めて何か他に良い方法がないか、もう少し調べてみたいと思います。
    丁寧なご回答で参考になりました。ありがとうございます。

    キャンセル

+1

本質は GET がページネーションによるものか、それとも他から飛んできた初期表示なのか、を区別する方法があるかどうかです。
手順としては以下のようにすればすっきりするはずです(コントローラー内)

  1. POST か GET かを切り分ける $this->request->is('POST')
  2. POST ならパラメータを元に検索条件を設定する
  3. GET であれば、遷移元をチェックする $this->request->env('HTTP_REFERER')
    3-1.
    遷移元のURLが表示する予定のURLと一致しない(クエリーパラメータ部分を除いて)なら、セッション上から検索条件を取り除く
    3-2.
    セッションから検索条件を取り出して(3-1が動いた場合は検索条件がすべて未設定と同じになる)、検索条件を設定する
  4. 検索条件(2もしくは3-2で決定している)をセッションに保存する

余談:検索条件を変更して飛んできた場合でも、ページネーションの情報も合わせて飛んでくる(クエリパラメータとして)ため、例えばある程度進んだページを表示しているときに検索条件を変えた結果、その検索条件ではそのページ番号まで到達しない場合、ページネーションで例外(NotFoundException)が発生します。

その場合はページ番号を1にしたURLを作って、そこにリダイレクトするとよいです。

try {
  $data= $this->paginate($data_all);
} catch (Cake\Http\Exception\NotFoundException $ex) {
  // 検索条件が変わったなどでページがない場合、ページを1にリセットして呼び直す  
  $redirect_url = preg_replace('/page=\d+/', 'page=1', $this->request->getUrl());
  $this->redirect($redirect_url);
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/15 18:17 編集

    ご回答ありがとうございます。遷移元のURL取得やページネーション例外時など参考になりました。
    上記の処理だと他の機能から遷移してきた時は問題ないのですが、メニューから同じ機能のリンクを押下した際や、F5ボタンなどで画面を更新した際も検索条件を初期化したいと考えているのですが、何か良い方法はありますでしょうか。もしあればご教授願いたいです。

    キャンセル

  • 2019/04/16 09:07

    リンクであればクエリーパラメータに「強制的に検索条件を初期化する」ようなフラグを追加して飛ばせばよいのでは。(そのフラグがある場合は 4. の直前で検索条件をクリアする)

    F5 は画面の再読込なので、条件を同じにするのが筋だと思います。

    キャンセル

0

なにもパラメータを渡さずにパラメータに基づいた表示をおこなうというのは
論理破綻しています

ただしクライアントが所定のページから次のページに移ったときに
カレントページを覚えておくということは
セッション、クッキー、localStorageなどを利用すれば可能です

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/10 12:20 編集

    説明不足で申し訳ありません。
    検索条件としてパラメータは渡すのですが、GETではなくPOSTなどで良い方法があればご教授願いたいです。
    「試したこと」にも記載しているように検索条件が見えない且つ検索結果の2ページ目が正常に表示されるように、POSTで実装しsessionで検索条件を保持してみたのですが、sessionの検索条件を破棄するタイミングが識別できず断念したという感じです。

    キャンセル

  • 2019/04/10 13:16

    セッションが使えるならページや検索条件を保持していれば正しく挙動するはずです

    キャンセル

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

  • PHP

    23494questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • トップ
  • PHPに関する質問
  • CakePHP3のPaginator機能を使用した上で、検索条件がGETパラメータなどで見えないようにPOSTでの実装方法を教えていただきたいです。