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

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

新規登録して質問してみよう
ただいま回答率
85.50%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

Q&A

4回答

1819閲覧

ページングを機能させたい

ariiiiiga

総合スコア66

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

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

0グッド

1クリップ

投稿2019/01/30 07:26

前提・実現したいこと

データベースから検索に該当したデータを取得する機能をつくってます。
検索からデータの取得はでき、次にページング機能を追加したいのですが上手くいきません。

検索結果のlimitを10とし、検索結果が15個ヒットし1ページ目は10個取得できているのですが、次へを押すと"検索対象は見つかりませんでした。"がでてしまいます。

問題個所の選定ができていないのですが、HTML内の結果表示の部分が間違えている気がします。
宜しくお願い致します。

該当のソースコード

<?php //--------------①検索用ここから------------------> function getHostData($params){ if(!isset($params['search'])){ return[]; } try{ $pdo = new PDO('mysql:host=localhost;dbname=mydb;charset=utf8','root','', array(PDO::ATTR_EMULATE_PREPARES => false)); } catch (PDOException $e) { exit(); } if(!empty($params['name'])){ $where[] = "name like '%{$params['name']}%'"; } if($where){ $whereSql = implode(' OR ', $where); $sql = 'select * from hosts where ' . $whereSql ; }else{ $sql = 'select * from hosts'; } $sql .= " order by post_id desc"; //SQL文を実行する $HostDataSet = $pdo->query($sql); //扱いやすい形に変える $result = []; while($row = $HostDataSet->fetch( PDO::FETCH_ASSOC )){ $result[] = $row; } return $result; } //--------------①検索用ここまで------------------> //---------------②ページング用ここから------------- $p = isset($_GET['p']) ? intval($_GET['p']) : 0; $limit = 10; $v_page = $limit + 1; $offset = $p * $limit; $pdo=new PDO('mysql:host=localhost;dbname=myhostlog_db;charset=utf8','root',''); $sql=$pdo->prepare('select * from hosts order by post_id desc limit :limit offset :offset '); $sql->bindValue(":limit", $v_page, PDO::PARAM_INT); $sql->bindValue(":offset", $offset, PDO::PARAM_INT); $sql->execute(); $hostData=[]; //---------------②ページング用ここまで------------- ?> <!DOCTYPE HTML> <html lang="ja"> <head> <meta charset="utf-8" > <title>トップページ</title> </head> <body>   <!-------------検索欄ここから---------------------> <div class="col-xs-6 col-xs-offset-3 well"> <form method="get"> <div class="form-group"> <label for="InputName">名前</label> <input name="name" class="form-control" id="InputName" value="<?php echo isset($_GET['name'])? htmlspecialchars($_GET['name']) : '' ?>"> </div> <button type="submit" class="btn btn-default" name="search">検索</button> </form> </div>    <!--------検索欄ここまで---------> <?php //--------------結果表示ここから---------------> if(!empty($_GET)){ $hostData = getHostData($_GET);?> <div class="col-xs-6 col-xs-offset-3"> <?php if(isset($hostData) && count($hostData)): ?> <p class="alert alert-success"><?php echo count($hostData) ?>件見つかりました。</p> <table class="table"> <thead> <tr> <th>名前</th> </tr> </thead> <tbody> <?php while ($row = $sql -> fetch(PDO::FETCH_ASSOC)){ echo '<tr>'; echo '<td>', htmlspecialchars($row['name']),'</td>'; echo '</tr>'; } ?> </tbody> </table> <?php else: ?> <p class="alert alert-danger">検索対象は見つかりませんでした。</p> <?php endif; ?> </div> <?php } ?> <br> <!--------結果表示ここまで---------> <?php //----ページング用ここから------ $pdo=new PDO('mysql:host=localhost;dbname=mydb;charset=utf8','root',''); $sql=$pdo->query('select * from hosts'); $total_res=$sql->rowCount(); $next_num = $p+1; $prev_num = $p-1; $total_page= ceil($total_res / $limit); if($p > 0){ echo '<a href="2.php?p=', $prev_num, '">前へ</a>','</td>'; } else { echo '最新'; } if($total_page-1 > $p){ echo '<a href="2.php?p=', $next_num, '">次へ</a>','</td>'; } else { echo '末尾'; } //----ページング用ここまで------ ?> </body> </html>

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/01/30 07:43 編集

同じテーブルに対するselectは一回にまとめないとゴチャゴチャにしかなりませんよ。できれば作り直してください。
ariiiiiga

2019/01/30 11:07

$sql=$pdo->prepare('select * from hosts order by post_id desc limit :limit offset :offset '); $sql=$pdo->query('select * from hosts'); この二つをまとめるということでしょうか? どうするべきなのか教えていただけませんか?
m.ts10806

2019/01/30 11:09

回答読んでください。 作り直さないといけないレベルです。そこをめんどくさがっていてはページングすらまともにできませんよ。
guest

回答4

0

ajaxで処理した方が早いんじゃないですか?
それと毎回同じようなことお伝えしてる気がしますが

  • try節内ですべてのpdoの処理をしなければエラーをつかめないですよ
  • パラメータはprepareでわたしてください
  • getやpostはfilter_inputしてください

投稿2019/01/30 10:05

yambejp

総合スコア114572

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/01/30 10:07 編集

こういったアドバイスを無視している内にどんどん手に負えないコードになっていくんですよね… もはや作り直した方がいいレベルに来てます
ariiiiiga

2019/01/30 11:06

・パラメータはprepareでわたしてください ・getやpostはfilter_inputしてください どの部分をどうしたらいいのか教えていただけませんか?
guest

0

淡々と指摘

php

1<?php 2//--------------①検索用ここから------------------> 3function getHostData($params){ 4 if(!isset($params['search'])){ 5 return[]; //これ返したらどうなるかわかって入れてるのだろうか 6 } 7 try{ 8 $pdo = new PDO('mysql:host=localhost;dbname=mydb;charset=utf8','root','', 9 array(PDO::ATTR_EMULATE_PREPARES => false)); 10 } catch (PDOException $e) { 11 //せっかくException捕捉してるのにその内容をどこにも出さないのでは問題が何か分からない。 12 //というか、接続のところだけcatchしても意味がない。全ての処理がうまくいく保障なんてないのでDB関係の処理は一通り囲っておくべき 13 exit(); 14 } 15 16 if(!empty($params['name'])){ 17 $where[] = "name like '%{$params['name']}%'"; 18 }//SQLインジェクション対策してください。 19 20 if($where){ 21 $whereSql = implode(' OR ', $where); 22 $sql = 'select * from hosts where ' . $whereSql ; //ここしか使わない変数なら定義しなくていい 23 }else{ 24 $sql = 'select * from hosts'; 25 } 26 //前から思ってたけど select * from hosts まで共通なら 分岐する必要ない。$whereが配列ならカウント0より大きいときにwhereを付帯したwhere句を作ればいい 27 /* 例: 28 $whereSql = ""; 29 if(count($where) > 0){ 30 $whereSql = " where ".implode(' OR ', $where); 31 } 32 $sql = 'select * from hosts'.$whereSql; 33 */ 34 35 36 $sql .= " order by post_id desc"; 37 38 //SQL文を実行する 39 $HostDataSet = $pdo->query($sql); 40 //扱いやすい形に変える 41 $result = []; 42 while($row = $HostDataSet->fetch( PDO::FETCH_ASSOC )){ 43 $result[] = $row; 44 } 45 //fetchAll()にすればwhile不要 46 return $result; 47} 48//--------------①検索用ここまで------------------> 49 50//---------------②ページング用ここから------------- 51$p = isset($_GET['p']) ? intval($_GET['p']) : 0; 最後の方に同じような処理があるから無駄では? これ何の処理? 52$limit = 10; 53$v_page = $limit + 1; 54$offset = $p * $limit; 55$pdo=new PDO('mysql:host=localhost;dbname=myhostlog_db;charset=utf8','root',''); //何回も接続するのは意味がない。 56$sql=$pdo->prepare('select * from hosts order by post_id desc limit :limit offset :offset '); 57$sql->bindValue(":limit", $v_page, PDO::PARAM_INT); 58$sql->bindValue(":offset", $offset, PDO::PARAM_INT); 59$sql->execute(); 60 61//これだと検索したときと一緒にできない 62 63$hostData=[]; 64//---------------②ページング用ここまで------------- 65 66?> 67<!DOCTYPE HTML> 68<html lang="ja"> 69<head> 70<meta charset="utf-8" > 71<title>トップページ</title> 72</head> 73 <body> 74  <!-------------検索欄ここから---------------------> ←この全角スペースは何? 75 <div class="col-xs-6 col-xs-offset-3 well"> 76 <form method="get"> 77 <div class="form-group"> 78 <label for="InputName">名前</label> 79 <input name="name" class="form-control" id="InputName" value="<?php echo isset($_GET['name'])? htmlspecialchars($_GET['name']) : '' ?>"> 80 </div> 81 <button type="submit" class="btn btn-default" name="search">検索</button> 82 </form> 83 </div> 84   <!--------検索欄ここまで---------> ←この全角スペースは何? 85 86 <?php 87 //--------------結果表示ここから---------------> 88 if(!empty($_GET)){ // $_GETの存在はチェックする必要ないのでは 89 $hostData = getHostData($_GET);?> // $_GETはスーパーグローバル変数なので引数で渡す必要はなし。 90 <div class="col-xs-6 col-xs-offset-3"> 91 <?php if(isset($hostData) && count($hostData)): ?> 92 <p class="alert alert-success"><?php echo count($hostData) ?>件見つかりました。</p> 93 94 <table class="table"> 95 <thead> 96 <tr> 97 <th>名前</th> 98 </tr> 99 </thead> 100 <tbody> 101 <?php 102 while ($row = $sql -> fetch(PDO::FETCH_ASSOC)){ //$hostDataのデータが無駄になった。 103 //「検索結果0件」はlimitやoffsetで絞っても0は0なのでそのためだけに$hostDataを作るのはコストが高すぎる。 104 //例え10件ページングで12件ヒットしたとして「p=3」とブラウザのURL切り替えられても「検索結果0」というのは理論的に合っている 105 echo '<tr>'; 106 echo '<td>', htmlspecialchars($row['name']),'</td>'; 107 echo '</tr>'; 108 } 109 ?> 110 </tbody> 111 </table> 112 113 <?php else: ?> 114 <p class="alert alert-danger">検索対象は見つかりませんでした。</p> 115 <?php endif; ?> 116 </div> 117 <?php } ?> 118 <br> 119 <!--------結果表示ここまで---------> 120 121 <?php 122 //----ページング用ここから------ 123 $pdo=new PDO('mysql:host=localhost;dbname=mydb;charset=utf8','root',''); //何回も接続するのは意味がない。 124 $sql=$pdo->query('select * from hosts'); //全件の件数取りたいだけならこれは無駄。 select count(column) table_name で充分 125 $total_res=$sql->rowCount(); 126 127 $next_num = $p+1; 128 $prev_num = $p-1; 129 $total_page= ceil($total_res / $limit); 130 131 if($p > 0){ 132 echo '<a href="2.php?p=', $prev_num, '">前へ</a>','</td>'; //検索条件もつけないと他のページで対応できない(今回質問者が聞いていること) 133//,でも動かないことはないけど意味合いとしては「文字列連結」だから . の方が適切。統一すべき 134 } else { 135 echo '最新'; 136 } 137 138 if($total_page-1 > $p){ 139 echo '<a href="2.php?p=', $next_num, '">次へ</a>','</td>';//検索条件もつけないと他のページで対応できない(今回質問者が聞いていること) 140 } else { 141 echo '末尾'; 142 } 143 //----ページング用ここまで------ 144 145 /* 146 SQLは下記2本で充分今回の対応が可能 無駄なDB接続・SQL実行が多すぎるのでデータ件数が何千件何万件となったときかなり危険 147 select * from hosts $whereSql に offset limit つけたもの(要は現ページに表示するデータ) 148 149 select count(*) from hosts $whereSql (要は検索結果の全件数) 150 151 */ 152 ?> 153 154 </body> 155</html> 156

リクエストパラメータについて基本的な知識がついていないことで非効率で拡張性もなく達成に向かっていないコードになっています。
下記きちんと読んで概念を理解してください

teratail内を探せば類似の問題はあります。

投稿2019/01/30 08:11

編集2019/01/30 13:31
m.ts10806

総合スコア80765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

「次へ」が通常リンクなので、一度「検索」押したときに出てくるクエリを、「次へ」のリンク先にもつけてあげればできると思います。

もしくは、「次へ」推したときにクエリを繋げるようにJSで処理させるとか。

投稿2019/01/30 07:44

kszk311

総合スコア3404

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ariiiiiga

2019/01/30 07:48

echo '<a href="2.php?p=', $next_num, '">次へ</a>','</td>'; この部分になにを追加したらいいのでしょうか?
kszk311

2019/01/30 07:50

「クエリ」を「GET値」と言い換えれば分かりますか?
ariiiiiga

2019/01/30 11:08

ありがとうございます! 検索結果表示のphp部分のechoの前を元々foreach($hostData as $row)にしていたのですが、ページング部分がうまくできなかったのでwhile ($row = $sql -> fetch(PDO::FETCH_ASSOC))にしました。 ですが、今度は検索ができず、検索をクリックすると全てのデータが表示されてしまいました。(ページングはできている) どちらを使った方がいいのか、あとそれを使った場合どこを直せばいいのか教えて頂きたいです。 お手数ですがよろしくお願いします。
guest

0

原因は、

php

1function getHostData($params){ 2 if(!isset($params['search'])){ 3 return[]; // $params['search']が存在しないため、ここを通過している。 4 }

$params['search']と$params['name']が必要なので、

php

1 echo '<a href="2.php?p=', $next_num, '">次へ</a>','</td>';//ここを以下に修正する 2 echo '<a href="2.php?p=', $next_num, '&search='.rawurlencode($_GET['search']).'&name='.rawurlencode($_GET['name']).'">次へ</a>','</td>';

=== ここから追記 ===
$_GETの内容全部ををhrefに追記する処理です。

php

1 //----ページング用ここから------ 2 $pdo=new PDO('mysql:host=localhost;dbname=mydb;charset=utf8','root',''); 3 $sql=$pdo->query('select * from hosts'); 4 $total_res=$sql->rowCount(); 5 6 $next_num = $p+1; 7 $prev_num = $p-1; 8 $total_page= ceil($total_res / $limit); 9 10 $tmp = $_GET; 11 if($p > 0){ 12 $tmp['p'] = $prev_num; 13 echo '<a href="2.php?' . http_build_query($tmp) . '">前へ</a>','</td>'; 14 } else { 15 echo '最新'; 16 } 17 18 if($total_page-1 > $p){ 19 $tmp['p'] = $next_num; 20 echo '<a href="2.php?' . http_build_query($tmp) . '">次へ</a>','</td>'; 21 } else { 22 echo '末尾'; 23 } 24 //----ページング用ここまで------

投稿2019/01/30 08:02

編集2019/01/30 08:50
kaba

総合スコア314

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ariiiiiga

2019/01/30 08:14

ありがとうございます!できました! 検索条件がnameで探す場合とshopで探す場合があるのですが、修正案にshopを追加する事は出来ますか?
kaba

2019/01/30 08:18

if (isset($_GET['name'])) if (isset($_GET['shop'])) による分岐処理にて実装できます。 自力での実装は難しいですか?
ariiiiiga

2019/01/30 08:22

わからないです、、、
ariiiiiga

2019/01/30 10:50 編集

ありがとうございます! 検索結果表示のphp部分のechoの前を元々foreach($hostData as $row)にしていたのですが、ページング部分がうまくできなかったのでwhile ($row = $sql -> fetch(PDO::FETCH_ASSOC))にしました。 ですが、今度は検索ができず、検索をクリックすると全てのデータが表示されてしまいました。(ページングはできている) どちらを使った方がいいのか、あとそれを使った場合どこを直せばいいのか教えて頂きたいです。 お手数ですがよろしくお願いします。
yambejp

2019/01/30 10:36

nameとshopの関係はand検索/or検索どちらですか?
ariiiiiga

2019/01/30 10:51

こちらのコメント内の3つ前の質問を変更いたしました。
kaba

2019/01/31 01:13

質問という形式をとった、作成依頼になっていませんか? わからないことを質問してわかるようになって、自力で実装できる実力を身に着けようという意思が感じられないのですが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問