dポイントプレゼントキャンペーン実施中!

PHPの簡易データ検索プログラムを書いていますがページャーを使ったデータ連動でうまくいかないところがあります。問題は1のデータ数取得がどのように2回(カウント+本検索)クエリを投げれば良いか判りません。どうかご教授いただきますようお願いします。
<?php
require_once "./rank/config.php";
require_once("Pager/Pager.php");

//【1】カウント用データベースに接続
$link = mysql_connect($server, $usr, $pass);
$db = mysql_select_db($mydb, $link);
$query = "SELECT COUNT(*) FROM detail WHERE category = '".$ID."'";
$count = mysql_query($query);
//【1】データ数の取得
$limit = $count;


$page = empty($_GET['p']) ? 1: $_GET['p'];
$offset = ($page - 1) * $limit;

// クエリ条件部分
$query = "SELECT * FROM detail";
$query .= " where 1";
$query .= " and category = '".$ID."'";
$query .= " limit {$limit} offset {$offset}";

$flag = true;
//MySQLデータベースに接続
if(!$link = mysql_connect($server, $usr, $pass)){
$flag = false;
}
//データベース選択
if(!$db = mysql_select_db($mydb, $link)){
$flag = false;
}
//lolipop用
mysql_set_charset("utf8");
//クエリ実行
if(!$result = mysql_query($query)){
$flag = false;
}
if(mysql_num_rows($result)==0){
echo 'データ件数は0件です';
}
$rows = mysql_num_rows($result);

if ($flag == true){
//メイン出力部
while($row = mysql_fetch_array($result,MYSQL_ASSOC)) {
$list[] = array(category =>$row["category"],area=>$row["area"]);
}
}else{
echo 'データベース接続エラー';
}
echo "<b>", $rows, "</b>件HITしました<br />\n";

$params = array(
'mode' => 'sliding',
'perPage' => $limit,
'itemData' => $list,
'firstPagePre'=>'=',
"firstPageText"=>"TOP",
"firstPagePost"=>"=",
"lastPagePre"=>"=",
"lastPageText"=>"LAST",
"lastPagePost"=>"=",
);

$pager = & Pager::factory($params);
$navi = $pager->getLinks();

print($pager->numItems()."件中<br/>");
$scope = $pager->getOffsetByPageId();
print($scope['0']."件目から".$scope['1']."件目を表示 <br/>");
$ary = $pager->getPageData();

foreach ($ary AS $key => $value) {
echo "<br>□1<br>".$value["category"]."<br>";
echo "□2<br>".$value["area"]."<br>";

echo "<hr>";
}
echo $navi['all'];

//SQLの解放
mysql_free_result($result);
mysql_close($link);

?>

A 回答 (10件)

はじめまして。

私はシステム開発を行っている者です。数ヶ月前の質問でしたのでもう解決されたかも知れませんが、同様の事象でお困りの方を対象に参考として回答させていただきます。

PEAR の Pager に検索データを全て入れて普通に処理すると、Pager では数万件のデータがある場合も一旦全部読み込んでしまうために、特に制限の多いレンタルサーバーでは PHP のメモリが足りなくなります。各ページ10件ごとの表示であれば、総データ数のみ取得した上で10件分だけデータを読み込んでくれれば、メモリ消費は少なくなります。

色々な方法があるかと思いますが、Pager_Wrapper.php を使用すると、これを簡単に行うことが出来ます。Pager_Wrapper.php は、Pager の /examples/ ディレクトリに入っていますので、これを取り出し /Pager/ ディレクトリと同階層に置きます。英語のサイトですが、以下のサイトの Method #2 が参考になると思います。

http://www.alberton.info/pear_pager_tutorial_dat …

「skipped the db connection code...」とあるように、$db については省略されていますので、このままでは動きません。

Pager_Wrapper.php のファイル中で require_once 'Pager/Pager.php'; は記述されていますので、作成されるスクリプトの中では require_once 'Pager_Wrapper.php'; と記述し、require_once 'Pager/Pager.php'; は記述の必要はありません。総データ数については、上記サイトの例では $paged_data['totalItems'] に入っています。itemData でデータを Pager に渡してやる必要もありません。作業工数は格段に減るはずです。
    • good
    • 0

軽く流し読みしただけですが・・



>$query = "SELECT COUNT(*) FROM detail WHERE category = '".$ID."'";
>$count = mysql_query($query);
>//【1】データ数の取得
>$limit = $count;

SQLを実行しただけで件数は取得してませんね。
「$limit」の中にはSELECT COUNT(*)・・の結果リソースが入っています。

>// クエリ条件部分
>$query = "SELECT * FROM detail";
>$query .= " where 1";
>$query .= " and category = '".$ID."'";
>$query .= " limit {$limit} offset {$offset}";

で、$limitを上記SQLで使用しているからSQLエラーになってます。


●結果
「$limit」の値を見直してみましょう!

この回答への補足

mookun2007さんこんばんは。
まずは、回答ありがとうございます。
確かにカウント部分がおかしかったので以下のように変えてみました。
何故か$rowsのカウントが”0”の所に問題がありそうです。
もう少し検証してみます!!

    
    //MySQLデータベースに接続
$link = mysql_connect($server, $usr, $pass);
//データベース選択
$db = mysql_select_db($mydb, $link);

echo "<b>IDは:", $ID, "</b><br />\n";
//カウントSQL部
$query = "SELECT * FROM detail";
$query .= " where 1";
$query .= " and category = '".$ID."'";

$result = mysql_query($query);
$rows = mysql_num_rows($result);

echo "<b>resultは:", $result, "</b><br />\n";
echo "<b>rowsは:", $rows, "</b><br />\n";
echo "<b>pageIDは:", $_GET['pageID'], "</b><br />\n";

$limit = 3;     //元々$rowsだがテスト用に適当
$page = empty($_GET['pageID']) ? 1: $_GET['pageID'];
$offset = ($page - 1) * $limit;

補足日時:2010/08/03 00:21
    • good
    • 0

こんにちは。



なんか、だんだんぐちゃぐちゃになってきたような・・・。
断片的に載せられても、エラーを特定するのは難しいです。

補足で載せて頂いたSQL自体には問題がないと思われます($IDの値が入っているので)。
それでもmysql_num_rowsの結果が取れないのなら、
1.本当に結果が0件だった・・・。
2.直前のmysql_query($query);に2番目の引数(データベースのコネクション)を渡していないため、デフォルトのコネクションを使用しようとしたが、それも存在しなかった・・・。結果的にSQLが発行できなかった。

これぐらいしか考えられません。

関係ないですが、「where 1」と書くのはどうかと思います。
(この書き方はRDMSの種類によってはエラーになります→汎用的ではない)
不要なら書かないか、どうしても必要なら「where 1 = 1」と書く方がいいと思います。

この回答への補足

回答ありがとうございます。
1.検索結果はその後の本検索部でデータを取得していますのであり得ません。
2.これも1と同様でコピーしているのであり得ません。
『where 1』というのは作りこみの次のステップとして条件を複数追加した時に条件が”無し”のパターンに対応するためです。これは調べて発見しました。
mySQLでの不都合が書かれていればもっと良かったように思います。

補足日時:2010/08/02 23:42
    • good
    • 0

こんにちは。



SQL発行するたびに、データベース接続してるんですね???
これも???ですが、先ほどの回答は一部訂正します。
    • good
    • 0

こんにちは。



なんかよくわかりません・・・。
まずCOUNTのSQLでこけてるなら、$IDの値を見てみるべきでしょう?
なぜ見ないんですか???
それと、
>(2)以下をコメントにし$limit=2;にすると
データベースに接続するところも一緒にコメントになってますが?
普通に考えたら、これでも動かないのに、結果が出てるのもおかしい・・・。

COUNTのSQLでエラーになってるところまでわかってるんだから、そこを修正すればいいだけなのに・・・。

この回答への補足

まず、文頭を以下のように書き換えてみました。
================================================
echo "<b>IDは:", $ID, "</b><br />\n";
//カウントSQL部
$query = "SELECT * FROM detail";
$query .= " where 1";
$query .= " and category = '".$ID."'";
$result = mysql_query($query);
$data_cnt = mysql_num_rows($result);

echo "<b>Countは:", $data_cnt, "</b><br />\n";

================================================
そしてechoで確認しましたが$IDは値が入っています。

しかし、$data_cntはなぜか0件になってしまいました。
(本検索部と同様に書いたつもりですが)

返信が拙くて申し訳ございません。
具体的にどこか構文がおかしな所がありますか?

補足日時:2010/08/01 21:00
    • good
    • 0

こんばんは。



先ほども回答しましたが、2ページ目の表示時に、$IDには値が入ってるんですか?
これをまず調査してください。
PHPのエラーが出ている場合は、エラーもそのまま載せてください。
現状が把握できないので、なんともしようがないです・・・。

この回答への補足

(1)phpをそのまま実行すると以下の■の行でエラー内容は以下になります。
■if(mysql_num_rows($result)==0){
Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource
■$rows = mysql_num_rows($result);
Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource
データベース接続エラー件HITしました
件中
1件目から件目を表示
■mysql_free_result($result);
Warning: mysql_free_result(): supplied argument is not a valid MySQL result resource

(2)以下をコメントにし$limit=2;にすると
/* 
//【1】カウント用データベースに接続
$link = mysql_connect($server, $usr, $pass);
$db = mysql_select_db($mydb, $link);
$query = "SELECT COUNT(*) FROM detail WHERE category = '".$ID."'";
$count = mysql_query($query);
//【1】データ数の取得
*/
$limit = $count;

データが2件表示されます。
データ1
 ・
 ・
データ2
 ・
 ・

※ページャー部分は表示されていません。


【結果】検証時にいろいろと弄ったことが影響したのか現在のphpでは以上のエラー内容でした。訂正いたします。
データを取得するSQLを投げる際に、limitやoffsetを変数で実行するためその値(対象データ数)を前もってもう一回SQLを投げて取得しておかなければいけません。そこがどうもうまくいきません。limitやoffsetを数値にすればデータは表示されます。
(値が固定のため、データ数が増えると今度はその分は表示されません)

お判りの部分がございましたらよろしくお願いします。

補足日時:2010/07/31 21:37
    • good
    • 0

こんばんは。



参考になるサイトと言われても・・・、
guppy8さんが示されたサイトの「前回ページャーを作りましたが」のリンクで作成してます。
そもそも、COUNTのSQLエラーを直せばいいだけじゃないんですか?
他にも問題点が多いんですか?

この回答への補足

>COUNTのSQLエラーを直せばいいだけじゃないんですか?

●上記phpでの具体例をお願いします。
独学で進めてきた結果、そこが判らないので今回の質問に至っております。

目的は上記プログラムで1ページ10件表示のデータ検索がしたいだけです。
総データ数は固定ではなくどんどん増えていく予定です。

補足日時:2010/07/31 20:11
    • good
    • 0

こんばんは。



その「ページャー」というものを使った事がないのでアレなんですが・・・、
COUNTのSQLでこけてるとすれば、2ページ目の表示時に$IDが飛んできてないような?
そこしか、こけるところがありません。
ページ制御なんて、自作した方が早いと思うけど・・・。

この回答への補足

taka451213さん回答ありがとうございます。

すみません、select countの書き方がおかしいのかもしれません。

>ページ制御なんて、自作した方が早いと思うけど・・・。
よろしければ自作したページ制御の参考になるサイトを教えていただけませんか?

正直ここで一ヶ月も止まってしまい、迷走してる感はあります。

補足日時:2010/07/31 18:30
    • good
    • 0

こんにちは。



ますますわからなくなってきましたが・・・、
>残りのデータが表示されない
ここでいう$limitと$offsetは大丈夫なんですか?
(値が入ってますか?)

この回答への補足

度々恐れ入ります。
正確には少し間違っておりました。
$limitは値を指定した場合のみ
(例:$limit=2;)
=========
データ1
データ2

1 2 >>

になります。(しかし、2を押した時に次のページデータを表示できません)


そして現状はSQLの実行エラーになるので$countが値なし。。
カウントのSQL文が間違っているような気がします。。

※独学でここまできましたがlimitとoffsetをページャーと連動させる方法がいまいちよくわかりません。ネットでも書籍でも情報が少ないようで。

補足日時:2010/07/31 17:49
    • good
    • 0

こんにちは。



どこがわからないのかが、いまいちわからないのですが・・・、
MySQLなので、2回もクエリ投げずに、
// クエリ条件部分
$query = "SELECT * FROM detail";
$query .= " where 1";
$query .= " and category = '".$ID."'";
$query .= " limit {$limit} offset {$offset}";

// クエリ条件部分
$query = "SELECT SQL_CALC_FOUND_ROWS * FROM detail";
$query .= " where 1";
$query .= " and category = '".$ID."'";
$query .= " limit {$limit} offset {$offset}";
に変えて、
$count = mysql_query('SELECT FOUND_ROWS()');
で総件数が取得できますよ。

全然関係ない回答ですかね?

この回答への補足

taka451213さん早速の回答ありがとうございます。
参考にして作成したのは以下のページです。
http://yuubiseiharukana.blog.shinobi.jp/Entry/118/ 
ソース部の下にカウントで件数をとり、データを取りそしてページャーに表示させる
となっているのでページャーを使う場合はカウントを二回投げないといけないと思っておりました。(調べたら他の方の書き込みでもそのような回答がありました)

現状上記phpを実行すると

=======
データ1
データ2

1 2 次へ>>

まで何とか表示されますが
●【2】をクリックし次のページに行った時に残りのデータが表示されないので困っている次第であります。


判りにくくてすみません、本当に困っていますのでどうかよろしくお願いします。

補足日時:2010/07/31 16:31
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!