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

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

ただいまの
回答率

91.05%

  • PHP

    17258questions

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

  • MySQL

    4956questions

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

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

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 144

hyou143

score 2

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>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+1

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

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

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/10 01:35

    ご解答ありがとうございます。
    こちらのページを見つけて参考にさせていただいているのですがこちらでも実装は可能でしょうか。

    https://qiita.com/tabo_purify/items/fb902956c1e1a3c75041

    キャンセル

  • 2018/01/10 01:42 編集

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

    キャンセル

  • 2018/01/10 01:49

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

    キャンセル

+1

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

LIMIT 1 OFFSET 0  -> LIMIT $offset, 1

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

LIMITで行数を制限する

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

まず、ページングの区切り方を考えます。例えば、データが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ページ目にアクセスした場合を考慮しなければなりません。

//オフセット初期値
$offset = 0;

//2件ずつ表示
$limit = 2;

if ($page > 0) {
    $offset = ($page - 1) * $limit;
}

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

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

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

//-----ページング機能
$form_lon = filter_input(INPUT_GET, 'longitude', FILTER_SANITIZE_NUMBER_FLOAT);
$form_lat = filter_input(INPUT_GET, 'latitude', FILTER_SANITIZE_NUMBER_FLOAT);

$offset = 0;
$limit  = 1;

//ページ番号取得
$p = (int)filter_input(INPUT_GET, 'page', FILTER_SANITIZE_NUMBER_INT);
$p = $p < 1 ? 1 : $p;

//オフセット決定
$offset = ($p - 1) * $limit;

//グローバルに保存(TextSearchDB()の引数に変更)
//$GLOBALS['limit']  = $limit;
//$GLOBALS['offset'] = $offset;

//...

//-----データベースから、指定した緯度経度を持つテキストファイルを検索する関数。
function TextSearchDB($longitude_num, $latitude_num, $limit, $offset)
{
    //...

    //プリペアードステートメント
    $stmt = mysqli_stmt_init($db_link1);

    //データ件数を取得
    mysqli_stmt_prepare($stmt, "SELECT count(*) FROM `img_table` WHERE (`longitude` BETWEEN ? AND ?) AND (`latitude` BETWEEN ? AND ?)");
    mysqli_stmt_bind_param($stmt, 'ssss', $com_longitude_minus, $com_longitude_plus, $com_latitude_minus, $com_latitude_plus);
    mysqli_stmt_execute($stmt);

    mysqli_stmt_bind_result($stmt, $total);
    mysqli_stmt_fetch($stmt);
    mysqli_stmt_free_result($stmt);

    $result = array();

    //データ件数以上の時(データがゼロ件の時、4ページのみで5ページ目にアクセスした場合)
    if ($offset > $total - 1) {
        echo '';
        return $result;
    }

    //-----指定した緯度経度のテキストを検索
    mysqli_stmt_prepare($stmt, "SELECT * FROM `img_table` WHERE (`longitude` BETWEEN ? AND ?) AND (`latitude` BETWEEN ? AND ?) ORDER BY `id_col` ASC LIMIT ? OFFSET ?");
    mysqli_stmt_bind_param($stmt, 'ssssii', $com_longitude_minus, $com_longitude_plus, $com_latitude_minus, $com_latitude_plus, $limit, $offset);
    mysqli_stmt_execute($stmt);

    //**** mysqlndが使える場合 ****
    $rs = mysqli_stmt_get_result($stmt);
    while ($row_lon = mysqli_fetch_array($rs)) {
        echo $row_lon['comment'];
        $result[] = $row_lon;
    }

/*
    //**** mysqlndが使えない場合 ****
    //bind_result() のためのカラム名をすべて取得
    $meta = mysqli_stmt_result_metadata($stmt);
    $args = [$stmt];

    while ($field = mysqli_fetch_field($meta)) {
        $args[] = &$column[$field->name];
    }

    //一気にバインド
    call_user_func_array('mysqli_stmt_bind_result', $args);

    //DBデータ取得
    while (mysqli_stmt_fetch($stmt)) {
        $row_lon = array();
        foreach($column as $k => $v) {
            $row_lon[$k] = $v;
        }
        echo $row_lon['comment'];
        $result[] = $row_lon;
    }
*/

    mysqli_stmt_free_result($stmt);
    mysqli_stmt_close($stmt);
    mysqli_close($db_link1);

    return $result;
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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

  • PHP

    17258questions

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

  • MySQL

    4956questions

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