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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

Q&A

解決済

3回答

1790閲覧

mysqlとphpを用いたページング機能の実装

hyou143

総合スコア9

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

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

0グッド

0クリップ

投稿2018/01/09 11:54

編集2018/01/09 12:22

phpとmysqlでページング機能を用いたデータの検索ページを作成しています。
limit offset句を使いフォームから入力したデータ(緯度経度の値)に合致するデータを1件ずつ表示させていくようなプログラムを目指して作成しているのですがページを更新しても表示データが変わりません。おそらくlimit offset句の扱い方が違うと予想しているのですが改善案が見つかりません。ご教授の方よろしくお願いいたします。

<html> <title>表示結果</title> <body> <fieldset> <legend>コメント</legend> <?php //データベースに接続する変数名を宣言しておく define( 'DB_HOST', '' ); define( 'DB_USER', '' ); define( 'DB_PASS', '' ); define( 'DB_NAME', '' ); //-----ページング機能 $form_lon = $_REQUEST['longitude']; $form_lat = $_REQUEST['latitude']; //$GLOBALS["offset"] = 0; $p=0; if(isset($_GET['page'])){ if(is_numeric($_GET['page'])){ $p=$_GET['page']; //$GLOBALS["offset"]= $p; } } $com_longitude = $form_lon; $com_latitude = $form_lat; //-----下の2つの関数を使い、緯度軽度に合致したテキストを表示する。 CallImg($com_longitude,$com_latitude); //-----指定した緯度経度を持つテキストを表示する関数 function CallImg($longitude_num,$latitude_num){ print TextSearchDB($longitude_num,$latitude_num); echo nl2br("\n"); } //-----データベースから、指定した緯度経度を持つテキストファイルを検索する関数。 function TextSearchDB($longitude_num,$latitude_num){ $com_longitude_minus = $longitude_num - 0.0005; $com_longitude_plus = $longitude_num + 0.0005; $com_latitude_minus = $latitude_num - 0.0005; $com_latitude_plus = $latitude_num + 0.0005; //-----データベースへ接続する $db_link1 = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME); $offset = $GLOBALS["offset"]; echo $offset; //-----指定した緯度経度のテキストを検索 $serch_query1 = mysqli_query($db_link1,"SELECT * FROM `img_table` WHERE (`longitude` BETWEEN '".$com_longitude_minus."' AND '".$com_longitude_plus."') AND (`latitude` BETWEEN '".$com_latitude_minus."' AND '".$com_latitude_plus."') ORDER BY `id_col` ASC LIMIT 1 OFFSET 0"); $row_lon = mysqli_fetch_array($serch_query1); echo $row_lon['comment']; $close_flag1 = mysqli_close($db_link1); } ?> </fieldset> <br> <fieldset> <legend>画像</legend> <!--<img src="image.php">--> </fieldset> <a href="?page= <?php echo $p+1;?> &longitude= <?php print($form_lon);?> &latitude= <?php print($form_lat);?>">次へ</a> </body> </html>

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

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

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

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

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

guest

回答3

0

まず、ページングの区切り方を考えます。例えば、データが5件で2件ずつ(LIMIT 2)表示する時のロジックを考えてみます。

//---- 1ページ目 ---- OFFSET == 0 //←ここが欲しい OFFSET == 1 //---- 2ページ目 ---- OFFSET == 2 //←ここが欲しい OFFSET == 3 //---- 3ページ目 ---- OFFSET == 4 //←ここが欲しい

ページが$page = nの時のオフセット$offsetを求めるには下記のように書けます。

※注意
$offset <= $total - 1 (オフセットはデータ件数-1以下)
例えば、4ページしかないのに5ページ目にアクセスした場合を考慮しなければなりません。

php

1//オフセット初期値 2$offset = 0; 3 4//2件ずつ表示 5$limit = 2; 6 7if ($page > 0) { 8 $offset = ($page - 1) * $limit; 9}

下記はページングを組み込んだサンプルです。質問にあるようにページングリンクは前後1つのみを考慮しています。複数ページングリンクを表示する場合は、もう少し複雑です。

XSSとSQLインジェクションを考慮して、filter_input()mysqli_stmt_init()を使うコードにしてあります。
また、$form_lon,$form_latTextSearchDB() の引数になっていますが、同じくDBパラメーターの $offset,$limit が引数でなかったので関数の引数に変更してあります。

PDOと違ってMysqlimysqlndドライバが使えない場合バインドしてからのデータ取得が非常に面倒ですが、mysqlnd ドライバが使える場合は非常に簡単です。

php

1//-----ページング機能 2$form_lon = filter_input(INPUT_GET, 'longitude', FILTER_SANITIZE_NUMBER_FLOAT); 3$form_lat = filter_input(INPUT_GET, 'latitude', FILTER_SANITIZE_NUMBER_FLOAT); 4 5$offset = 0; 6$limit = 1; 7 8//ページ番号取得 9$p = (int)filter_input(INPUT_GET, 'page', FILTER_SANITIZE_NUMBER_INT); 10$p = $p < 1 ? 1 : $p; 11 12//オフセット決定 13$offset = ($p - 1) * $limit; 14 15//グローバルに保存(TextSearchDB()の引数に変更) 16//$GLOBALS['limit'] = $limit; 17//$GLOBALS['offset'] = $offset; 18 19//... 20 21//-----データベースから、指定した緯度経度を持つテキストファイルを検索する関数。 22function TextSearchDB($longitude_num, $latitude_num, $limit, $offset) 23{ 24 //... 25 26 //プリペアードステートメント 27 $stmt = mysqli_stmt_init($db_link1); 28 29 //データ件数を取得 30 mysqli_stmt_prepare($stmt, "SELECT count(*) FROM `img_table` WHERE (`longitude` BETWEEN ? AND ?) AND (`latitude` BETWEEN ? AND ?)"); 31 mysqli_stmt_bind_param($stmt, 'ssss', $com_longitude_minus, $com_longitude_plus, $com_latitude_minus, $com_latitude_plus); 32 mysqli_stmt_execute($stmt); 33 34 mysqli_stmt_bind_result($stmt, $total); 35 mysqli_stmt_fetch($stmt); 36 mysqli_stmt_free_result($stmt); 37 38 $result = array(); 39 40 //データ件数以上の時(データがゼロ件の時、4ページのみで5ページ目にアクセスした場合) 41 if ($offset > $total - 1) { 42 echo ''; 43 return $result; 44 } 45 46 //-----指定した緯度経度のテキストを検索 47 mysqli_stmt_prepare($stmt, "SELECT * FROM `img_table` WHERE (`longitude` BETWEEN ? AND ?) AND (`latitude` BETWEEN ? AND ?) ORDER BY `id_col` ASC LIMIT ? OFFSET ?"); 48 mysqli_stmt_bind_param($stmt, 'ssssii', $com_longitude_minus, $com_longitude_plus, $com_latitude_minus, $com_latitude_plus, $limit, $offset); 49 mysqli_stmt_execute($stmt); 50 51 //**** mysqlndが使える場合 **** 52 $rs = mysqli_stmt_get_result($stmt); 53 while ($row_lon = mysqli_fetch_array($rs)) { 54 echo $row_lon['comment']; 55 $result[] = $row_lon; 56 } 57 58/* 59 //**** mysqlndが使えない場合 **** 60 //bind_result() のためのカラム名をすべて取得 61 $meta = mysqli_stmt_result_metadata($stmt); 62 $args = [$stmt]; 63 64 while ($field = mysqli_fetch_field($meta)) { 65 $args[] = &$column[$field->name]; 66 } 67 68 //一気にバインド 69 call_user_func_array('mysqli_stmt_bind_result', $args); 70 71 //DBデータ取得 72 while (mysqli_stmt_fetch($stmt)) { 73 $row_lon = array(); 74 foreach($column as $k => $v) { 75 $row_lon[$k] = $v; 76 } 77 echo $row_lon['comment']; 78 $result[] = $row_lon; 79 } 80*/ 81 82 mysqli_stmt_free_result($stmt); 83 mysqli_stmt_close($stmt); 84 mysqli_close($db_link1); 85 86 return $result; 87}

投稿2018/01/09 17:10

編集2018/01/09 17:18
Tomak

総合スコア1652

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

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

0

ベストアンサー

phpを実行環境が無いので、正しいか分かりませんが、
SQLの所を以下のように修正したらどうでしょうか

LIMIT 1 OFFSET 0 -> LIMIT $offset, 1

LIMIT 1 OFFSET 0
だと、常に最初の1件を取得 となっているように思います

LIMITで行数を制限する

投稿2018/01/09 16:15

Shara

総合スコア125

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

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

0

PDOで書いていますが、SQL部分はこちら参考になるかもしれません。

https://qiita.com/ShibuyaKosuke/items/0c5c6df1fac218fbca38

投稿2018/01/09 15:33

編集2018/01/09 15:34
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2018/01/09 16:42 編集

参考サイトのコードをちゃんと理解して、mysqli_に変更できるなら可能です。 ただし、PHPのバージョンによってはエラーになる記述が散見されます。
hyou143

2018/01/09 16:49

ご解答ありがとうございます。 開発環境はxamppを使用しておりphpのバージョンは7.1.11となっております。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問