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

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

ただいまの
回答率

90.32%

phpのページングについて

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,668

gik

score 146

// result.php

require( 'config.php' );
require( 'lib.php' );

//
if ( $_GET['page'] == '' ) $_GET['page'] = 0;
if ( $_GET['rows'] == '' ) $_GET['rows'] = 20;
if ( $_GET['sort'] == '' ) $_GET['sort'] = 'item_name asc';

//
session_start();

// db connect
$link = mysql_connect( $db_host, $db_user, $db_password );
mysql_select_db( $db_name );
$result = mysql_query( 'set character set utf8' );

//
if ( $_GET['author_id'] != '' ) $where .= "item.author_id = '" . mysql_real_escape_string( $_GET['author_id'] ) . "' and ";
if ( $_GET['category_id'] != '' ) $where .= "category_id = '" . mysql_real_escape_string( $_GET['category_id'] ) . "' and ";
if ( $_GET['query'] != '' ) $where .= "item_name like '%" . mysql_real_escape_string( $_GET['query'] ) . "%' and ";

$where .= 'item_id > 0';

$sql = "select * from item where $where";
$result = mysql_query( $sql );
$num_rows = mysql_num_rows( $result );

$sql = "select * from item 
    left join author on item.author_id = author.author_id 
    where $where order by " . mysql_real_escape_string( $_GET['sort'] ) . " limit ${_GET['page']}, ${_GET['rows']}";
$result2 = mysql_query( $sql );
//echo $sql;

//
$delta = 3 * $_GET['rows'];

if ( $_GET['page'] - $delta < 0 ) $s = 0; else $s =  $_GET['page'] - $delta;
if ( $_GET['page'] + $delta > $num_rows ) $e = $num_rows; else $e = $_GET['page'] + $delta;




?>
<? require( 'header.php' ) ?>
<? require( 'topbar.php' ) ?>
<div align="center">
<h2>検索結果<?= $num_rows ?>件中<?= $_GET['page'] + 1 ?>件から<?= $_GET['page'] + $_GET['rows'] ?>件までを表示</h2>
<table>
<? while ( $item = mysql_fetch_array( $result2 ) ) { ?>
<tr>
    <td>
        <a href="item.php?item_id=<?= $item['item_id'] ?>"><img src="<?= $item['image_url'] ?>" width=90 alt="<?= $item['item_name'] ?>" align="top" border=0></a>
    </td>
    <td>
        <a href="item.php?item_id=<?= $item['item_id'] ?>"><?= $item['item_name'] ?> <?= $item['author_name'] ?></a><br>
        価格 <?= $item['sale_price'] ?> 円(税込み)
    </td>
</tr>
<? } ?>
</table>
<? if ( $_GET['page'] >= $_GET['rows'] ) { ?>
<a href="result.php?page=<?= $_GET['page'] - $_GET['rows'] ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">前のページ&nbsp;</a>
<? } ?>
<? for ( $m = $s; $m <= $e; $m = $e++ ) { ?>
<a href="result.php?page=<?= $m ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">
<? if ( $m ==  $_GET['page'] ) echo "<big><b>" . $m / $_GET['rows'] . "</b></big>"; else echo $m / $_GET['rows'] ?></a>
<? } ?>
<? if ( $num_rows > $_GET['page'] + 1 ) { ?>
<a href="result.php?page=<?= $_GET['page'] + $_GET['rows'] ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">&nbsp;次のページ</a>
<? } ?>
<? require( 'footer.php' ) ?>
?

PHPによるECサイトプログラミング~ショッピングカートから決済まで―MySQLのデータベース設計とPHPセッション管理の作法 
という本を買って読んでいるのですが、
このresult.phpのページング処理がよくわかりません。
教えてください。
`
/*
* 変数eは 表示開始件数 + delta がnum_rowsより上回る時に最大件数
*(一番最後のページリンクを作るため)
* 上回る時には表示開始件数 + delta
* これは、現在のページより2ページ次のページまでページリンクを表示させたい為
*/
if ( $_GET['page'] + $delta > $num_rows ) $e = $num_rows; else $e = $_GET['page'] + $delta;
この部分で表示開始件数がわからないです。
この$_GET['page']はページ数のみgetするのはないのですか?
つまりたとえば$_GET['page'] + $_GET['rows']で1ページ目は20件、2ページ目1件まで、
$_GET['page']で2をゲットしたら22件ではないのですか?
$_GET['page']が表示開始件数を手にしている部分はどこですか?

<?php /* 表示開始件数が表示件数を上回る場合に戻るリンクを表示させます。*/ ?>
<? if ( $_GET['page'] >= $_GET['rows'] ) { ?>
<?php 
/*
* 現在の検索結果を引き継ぎたいのでとりあえずGETパラメータは全て入れる。
* 以下のURLを表示させます。
* result.php?page=[表示開始件数 - 表示件数]&rows=[表示件数]&author_id=[その他id]& category_id=[カテゴリID]&query=[商品名の一部か全部]&sort=[表示順]
*/
?>
<a href="result.php?page=<?= $_GET['page'] - $_GET['rows'] ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">前のページ&nbsp;</a>
<? } ?>
<!-- 戻るリンクの表示終了。 -->
表示開始件数と$_GET['page']がよくわかりません。
<?= $_GET['page'] - $_GET['rows'] ?>にするとマイナスになってしまうのでは?

<?php /*最大表示件数が表示開始件数を上回る場合に進むリンクを表示させます。*/ ?>
<? if ( $num_rows > $_GET['page'] + 1 ) { ?>
<?php 
/*
* 現在の検索結果を引き継ぎたいのでとりあえずGETパラメータは全て入れる。
* 以下のURLを表示させます。
* result.php?page=[表示開始件数 + 表示件数]&rows=[表示件数]&author_id=[その他id]& category_id=[カテゴリID]&query=[商品名の一部か全部]&sort=[表示順]
*/
?>
<a href="result.php?page=<?= $_GET['page'] + $_GET['rows'] ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">&nbsp;次のページ</a>
<? } ?>
<!-- 進むリンクの表示終了。 -->
<? require( 'footer.php' ) ?>

表示開始件数の意味と
$_GET['page']がページ数のみgetしていると思っていたのがもしかして
間違った解釈を私していると思うんです。
申し訳ありません。
そこのところ、もう少しわかりやすく教えてください
よろしくお願います



pageには、page番号ではなく表示開始件数が入ります。
っと書いてありますが、すいません。その記述はどこにあるのでしょうか?
$sql = "select * from item 
left join author on item.author_id = author.author_id 
where $where order by " . mysql_real_escape_string( $_GET['sort'] ) . " limit ${_GET['page']}, ${_GET['rows']}";
$result2 = mysql_query( $sql );

この部分も教えてください。
すいません。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • sounisi5011

    2015/06/25 19:16 編集

    コードが本文に直接書かれており非常に見づらいです。「```lang-PHP

    ```」の記法を使い、コードが分かりやすくなるよう修正を行って下さい。

    キャンセル

回答 3

checkベストアンサー

+1

/*
   * 前提として
   * $_GET['rows'] ・・・1ページあたりの表示件数
   * $_GET['page'] ・・・現在の表示開始件数
   */
//deltaには表示件数 * 3が入ります。
$delta = 3 * $_GET['rows'];
/*
  * 変数sは 表示開始件数 - delta が0より下回る時に0(一番最初のページリンクを作るため)
  * 上回る時には表示開始件数 - delta
  * これは、現在のページより2ページ前のページからページリンクを表示させたい為
  * ※ページリンク << [1 2 3 4] >> みたいなの
  */
if ( $_GET['page'] - $delta < 0 ) $s = 0; else $s =  $_GET['page'] - $delta;
/*
  * 変数eは 表示開始件数 + delta がnum_rowsより上回る時に最大件数
  *(一番最後のページリンクを作るため)
  * 上回る時には表示開始件数 + delta
  * これは、現在のページより2ページ次のページまでページリンクを表示させたい為
  */
if ( $_GET['page'] + $delta > $num_rows ) $e = $num_rows; else $e = $_GET['page'] + $delta;


?>
<?php /*header用のfile読み込み*/ ?>
<? require( 'header.php' ) ?>
<?php /*topbar用のfile読み込み*/ ?>
<? require( 'topbar.php' ) ?>
<?php 
    /*
      * $_GET['page'] + 1で現在の表示件数が何件目からかを取得。 
      * $_GET['page'] + $_GET['rows']で何件目までかを取得
      */
?>
<div align="center">
<h2>検索結果<?= $num_rows ?>件中<?= $_GET['page'] + 1 ?>件から<?= $_GET['page'] + $_GET['rows'] ?>件までを表示</h2>
<table>
<?php
    /*
      * ここから商品情報表示
      * DBから取得した値を行毎にitem変数に入れてます。
      * loopの開始
      */
?>
<? while ( $item = mysql_fetch_array( $result2 ) ) { ?>
<tr>
    <td>
         <!-- item変数から商品詳細リンクや商品画像を表示させます -->
         <!-- URL : item.php?item_id=[商品ID] -->
        <a href="item.php?item_id=<?= $item['item_id'] ?>"><img src="<?= $item['image_url'] ?>" width=90 alt="<?= $item['item_name'] ?>" align="top" border=0></a>
    </td>
    <td>
         <!-- item変数から商品詳細リンクと商品名や金額等を表示させます -->
         <!-- URL : item.php?item_id=[商品ID] -->
        <a href="item.php?item_id=<?= $item['item_id'] ?>"><?= $item['item_name'] ?> <?= $item['author_name'] ?></a><br>
        価格 <?= $item['sale_price'] ?> 円(税込み)
    </td>
</tr>
<? } ?>
<?php /*loop終了*/?>
</table>
<?php /*lここまで商品情報表示*/?>

<?php /* 表示開始件数が表示件数を上回る場合に戻るリンクを表示させます。*/ ?>
<? if ( $_GET['page'] >= $_GET['rows'] ) { ?>
<?php 
    /*
      * 現在の検索結果を引き継ぎたいのでとりあえずGETパラメータは全て入れる。
      * 以下のURLを表示させます。
      * result.php?page=[表示開始件数 - 表示件数]&rows=[表示件数]&author_id=[その他id]& category_id=[カテゴリID]&query=[商品名の一部か全部]&sort=[表示順]
       */
?>
<a href="result.php?page=<?= $_GET['page'] - $_GET['rows'] ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">前のページ&nbsp;</a>
<? } ?>
<!-- 戻るリンクの表示終了。 -->

<?php 
    /* TODO:ここバグってないかなと思う箇所。1回のみ実行されそう。。。
      * 最後のインクリメント部分 $m = $m + $_GET['rows']とかじゃないかな。
      * さっきの2ページ前から2ページ先までのリンク作成 
      */
?>
<? for ( $m = $s; $m <= $e; $m = $e++ ) { ?>
<!--ページリンク生成-->
<a href="result.php?page=<?= $m ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">
<?php /*現在のページ番号と同一の場合太文字にしてページ番号の表示*/ ?>
<? if ( $m ==  $_GET['page'] ) echo "<big><b>" . $m / $_GET['rows'] . "</b></big>"; else echo $m / $_GET['rows'] ?>

</a>
<? } ?>

<?php /*最大表示件数が表示開始件数を上回る場合に進むリンクを表示させます。*/ ?>
<? if ( $num_rows > $_GET['page'] + 1 ) { ?>
<?php 
    /*
      * 現在の検索結果を引き継ぎたいのでとりあえずGETパラメータは全て入れる。
      * 以下のURLを表示させます。
      * result.php?page=[表示開始件数 + 表示件数]&rows=[表示件数]&author_id=[その他id]& category_id=[カテゴリID]&query=[商品名の一部か全部]&sort=[表示順]
       */
?>
<a href="result.php?page=<?= $_GET['page'] + $_GET['rows'] ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">&nbsp;次のページ</a>
<? } ?>
<!-- 進むリンクの表示終了。 -->
<? require( 'footer.php' ) ?>

多分こんな感じ。

//条件に引っかかった値を全カラム取得
$sql = "SELECT "
.     "* "
. "FROM "
//item tableにauthor tableをauthor_idで結合
.     "item "
. "LEFT JOIN "
.     "author "
. "ON "
.     "item.author_id = author.author_id "
//検索用のWhereで絞り込み
. "where "
.     $where 
//並び順の設定
. "order by " 
.     mysql_real_escape_string( $_GET['sort'] ) 
//page件目からrows件のデータを取得
//TODO:ここインジェクションの脆弱性があるため、このままでは必ず実装しないこと
. " LIMIT ${_GET['page']}, ${_GET['rows']}";

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/06/29 09:23

    <a href="result.php?page=<?= $_GET['page'] + $_GET['rows'] ?>&rows=<?= $_GET['rows'] ?>&author_id=<?= $_GET['author_id'] ?>&category_id=<?= $_GET['category_id'] ?>&query=<?= $_GET['query'] ?>&sort=<?= $_GET['sort'] ?>">&nbsp;次のページ</a>
    <? } ?>

    ここ等のgetパラメータ付きのリンクを生成している場所で
    page + rows
    になっています。
    また、上の例で貼って頂いたpage部分でもlimit句の1つめにpageは入っている事から
    page = 表示開始件数であると予測できます。
    ページ番号であった場合貼って頂いたSQLも破綻しています。
    pageがページ番号と思った理由はなんですか?

    SQL文の説明を追記致しました。

    キャンセル

  • 2015/06/30 00:10

    ずっとそう思っていました。
    根拠があったわけでもなくすいません。
    解決しました。
    ありがとうございます。
    もっと勉強します

    キャンセル

  • 2015/06/30 11:21

    解決したようで何よりです。

    キャンセル

+1

mysql_real_escape_string があるので、インジェクションは大丈夫かな。limit句がエスケープされてないか…。
本に載っているコード自体が、素人が書きましたというようなコードなので、参考には値しませんね。
初版が2007年ということなのでmysql_*系を使っているのはやむなしとしても…
わざわざ買ってまで使うものではありませんね。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

これは本に書かれているままのコードなのでしょうかね…
その先に修正されたコードがあるならいいのですが、このコードのままだとするならサーバーにあげてはいけません。この短いコードの中にいくつも「やってはいけない」悪いコードが…

XSSとか…

この本だけではとても実用レベルの学習にはなりませんので、早々に卒業して、次のレベルで学習して下さい。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/06/26 09:26 編集

    はっきり言って窓から投げ捨てるレベルですよね。。。
    getパラメータsqlに直に入れてるのでインジェクションされますし。。。
    issetしてないし、htmlspecialcharsしてないし。。。

    キャンセル

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

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

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