人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHPについて質問です。

最初に正解に導いていただいた方に300ポイント差し上げます。
ただし回答が正解であっても私が理解できない可能性があります。
初心者の私が理解できたかどうかということで判断しますので、
あらかじめご了承ください。

googleの検索結果ページにある「1234・・」というようなリンクを作り、
データを1ページ10件ごとに分けて表示したいです。
一般的にはPearのpagerを使うのでしょうが、
うまく使えません。そこで下記のいずれかでご回答ください。

?Pearのpagerの使い方を初心者でもわかるよう説明してください。
これについてはネットで結構調べましたが解決できませんでした。

?あるいは下記のスクリプトの使い方を教えてください。
http://ryouchi.seesaa.net/article/45846102.html
たとえば50件あるデーを10件ずつ5ページに分けるよう設定したつもりですが、
「12345」という数字のリンクは表示されるだけで、
どのページも50件のデータが1ページに表示されます。
またこの関数に使われているidという概念もよくわからないので、
これは何を意味しているのかということも併せてご説明ください。

Vista,PHP5,Firefoxでやっています。
よろしくお願いします。

●質問者: taroemon
●カテゴリ:コンピュータ ウェブ制作
✍キーワード:firefox Google Pear PHP VISTA
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

1 ● goodvn
●20ポイント

http://www.phpbook.jp/pear/pear_pager/

この辺にある,サンプルプログラムを全部書き写して動かしてみましたか?

プログラムを覚えるには,ひたすら書くのも手です.ここで聞いてる時間に,コードをたくさん書いた方が覚えられると思います.

ちなみに,ご質問のページング処理というのは,ウェブサービスを作る上で,常に面倒な処理の一つです.PEAR::Pager も一つの手ですが,慣れてくれば,いろんな方法があることが分かるでしょう.

私の場合は,テンプレートエンジンに Smarty,元データは RMDBS(MySQLなど) を使うために,それに適した独自のページング処理を行っています.RMDBS の場合,SQL で,

LIMIT 21,11

といったように,ページングに適したデータ数が取得できるので,このデータを使うことで解決しています.11件取ってきてるのは,10件表示後に,まだ続きがあるかを知る事で,"次へ" のリンクを出すか決定するためです.

Google みたいなリンクを出す場合は,総数を知らないといけないので,そういう処理も必要ですね.

◎質問者からの返答

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

風邪を引いていたので、いただいたご回答を試すことができませんでした。

返事が遅れて済みません。

ご紹介いただいたリンク大変参考になりました。じっくり拝見します。


2 ● Quphondi
●20ポイント

私が実装したときに作ったミニマムの動作サンプルコードです。

<?php
require_once("Pager/Pager.php");

$totalItems = 50; // 表示対象となる全ての要素の数
 // RDBと連携する場合は、全要素数を取得する
$ROW_MAX = 10; // 1ページあたりの表示要素数

// 各ページの表示関数関数
function showPage($start,$cnt){
print("<li>Start:$start - Item Per Page:$cnt");
print("<ol>");
for($i=0; $i<$cnt; $i++){
$item = $start +$i;
print("<li>[$item]");
}
print("<ol>");
}

// Pager のパラメータ
$params = array(
"perPage" => $ROW_MAX,
"totalItems" => $totalItems,
);
$o_page = Pager::factory($params); // コンストラクタではなく、factoryで生成
$navi = $o_page->getLinks();
print($navi['all']);
print("<hr />");
showPage(($o_page->getCurrentPageID()-1)*$ROW_MAX,$ROW_MAX);
?>

Pear::Pager自体は、Pageナビゲーションの部分を生成してくれるだけです。ページ表示を行う部分(関数)は別途書く必要があります。上記のサンプルではshowPage()がそれに当たります。

RDBと連携しているのであれば、limit句、offset句で最大表示数と表示開始要素を指定してあげます。具体的にはこんなコードです。

$sql ="select * from db_samlpe limit $cnt offset $start;";

ひとまず、こんなところで

◎質問者からの返答

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

風邪を引いていたので、いただいたご回答を試すことができませんでした。

返事が遅れて済みません。


いただいたスクリプトをそのまま貼り付けてみたところ下記のようなエラーが複数できました。

Warning:: Unexpected character in input: ' in (中略)/Pager/Common.php on line 962

複数のエラーはいずれも962行目に関することのようです。

おそらくこれは簡単なことで解決できるのかもしれませんが、私にはうまくいきませんでした。

ちなみにRDBは使用していません。


急いでお返事するために、あまり時間をかけて試してません。

いただいたご回答を元にもう少しがんばってみようとお思います。


3 ● sakai
●20ポイント

2のスクリプトの使い方ですが、指定ページから10件表示するという処理は自分で作成しないといけません。

そのためには現在開いているページ番号を取得する必要があります。

ページ番号はどこに設定されているかというと、

pager関数の第一引数をidにした場合は、ページ毎のリンク先URLに?id=1といった形で設定されています。


実際にこの値を取り出すには、$_GETという配列を利用します。

$_GET['id']で現在開いているページ番号が取得できます。

ただし最初にページを開いた場合は$_GET['id']に何も入っていないので、$_GET['id']が空の場合は1ページにするという処理が必要になります。

あとはPER_PAGEに取得件数が定義されているので、この二つのデータを利用して取得するデータを絞りこんで下さい。


ご質問のあったidはページ番号のことです。

◎質問者からの返答

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

風邪を引いていたので、いただいたご回答を試すことができませんでした。

返事が遅れて済みません。


やっとこの関数のidのことが完全に理解することができました。

作成されたファイルには「12345」というリンクがあるのですが、

1ページ目のアドレスには「?id=1」という表記がありません。

2ページ目以降には?id=2」等とあるのですが、1ページ目と同じ内容になってしまいます。

また、1ページに10件ごとの情報を5ページ、合計50件の情報を表示したいのですが、

全部のページが1ページに50件の情報が掲載されているという状態になってしまいます。


急いでお返事するために、あまり時間をかけて試してません。

いただいたご回答を元にもう少しがんばってみようとお思います。


4 ● tobeoscontinue
●300ポイント ベストアンサー
?Pearのpagerの使い方を初心者でもわかるよう説明してください。
<?php
require_once 'Pager.php';

$data = range(1,50);

$params = array('mode'=>'Sliding','perPage'=>10,'delta'=>4,'itemData'=>$data);

$pager = & Pager::factory($params);
foreach ($pager->getPageData() as $d) echo "<p>$d</p>";
echo "<hr>";
echo $pager->links;
?>

$dataはテスト用のダミーデータです。

$paramsの'itemData'でPagerにデータを渡します。こうすることでgetPageData()で、そのページで表示する分だけのデータを受け取ることができます。後は$pager->linksでリンクのhtmlを表示できます。

factoryへ渡す$paramsについてはhttp://pear.php.net/manual/ja/package.html.pager.factory.phpで知ることができます。

データが小さい場合はいいのでしょうが、DB内のデータを全て取り込むというのでは現実的ではありません。

"totalItems"を指定すればgetOffsetByPageID()でfrom,toを入手できますので、それで必要な部分だけ読み込むことができます。http://www.alberton.info/pear_pager_tutorial_database_results.ht...

?あるいは下記のスクリプトの使い方を教えてください。

この関数はリンクのhtmlは生成しますが、データの表示については感知しません。

idはページ指定の受渡しのためにGETを用いているのですが、その名前を指定するものです。

Pearのpagerで言う"urlVar"です。(固定にすると名前がぶつかる場合があるための配慮ではないでしょうか。)

<?php
$data = range(1,50);

$f = (max(1, intval($_GET[PAGE_VALUE]))-1)*PER_PAGE;
$t = min($f+PER_PAGE, count($data))-$f;
foreach (array_slice($data, $f, $t) as $d) echo "<p>$d</p>";
echo "<hr>";
pager(PAGE_VALUE,count($data));
?>

$_GET[PAGE_VALUE]の値を表示とpager関数と別々に処理しないといけないというのはしっくりしませんが。


いずれにしろ、htmlの生成までしてしまうので気にいらなければ修正が必要になります。

pager関数のほうが小さくて簡単だと思いますがPearのpagerを真似て(微妙に異なります)Classにしてみました。

<?php
class Pager {
 private $params;
 private $now; // 現在ページ
 private $max; // 最大ページ
 function __construct($params) {
 $default = array("urlVar"=>'p',"url"=>$_SERVER['SCRIPT_NAME'].'?','delta'=>5,'perPage'=>10,
 'prevImg'=>'&lt;', 'nextImg'=>'&gt;', "separator"=>'&nbsp;|&nbsp;');
 $this->params = array_merge($default, $params);
 if (isset($params["itemData"]))
 $this->params["totalItems"] = count($params["itemData"]);
 $id = $this->params["urlVar"];
 $this->max = intval(($this->params["totalItems"]-1)/$this->params["perPage"])+1;
 $this->now = min(max(1, intval($_GET["$id"])), $this->max);
 }
 function getOffsetByPageID($now=NULL) {
 $now = ($now === NULL) ? $this->now : $now;
 $wing = $this->params["perPage"];
 $from = ($now-1)* $wing;
 return array($from, min($from+$wing, $this->params["totalItems"])-$from);
 }
 function getPageData($pageID=NULL) {
 list($s, $l) = $this->getOffsetByPageID($pageID);
 return array_slice($this->params["itemData"], $s, $l);
 }
 function rangeBar($delta) {
 $left = max(1, $this->now-$delta);
 $right = min($left+$delta+$delta-1, $this->max);
 if ($right-$left+1 < $delta+$delta) $left = max(1, $right-$delta-$delta+1);
 return range($left, $right);
 }
 function toAncher($no,$value) {
 return '<a href="'.$this->params["url"].$this->params["urlVar"].'='.$no.'">'.$value.'</a>';
 }
 function toArrow($no, $value) {
 return (0 < $no && $no <= $this->max) ? $this->toAncher($no, $value) : '';
 }
 function func_map($no) {
 return ($this->now != $no) ? $this->toAncher($no, $no) : $no;
 }
 function __toString() {
 return ($this->max < 2) ? '' :
 implode("&nbsp;:&nbsp;", array_filter(array(
 $this->toArrow($this->now-1, $this->params["prevImg"]),
 implode($this->params["separator"],
 array_map(array($this,"func_map"), $this->rangeBar($this->params["delta"]))),
 $this->toArrow($this->now+1, $this->params["nextImg"]))));
 }
}
?>

ぐっと詰めて書いたのでわかりづらいですがhtmlの部分はtoAncher()の一行です。

やっていることはrangeBar()で[1,2,3,...10]のような配列を作ることです。後はこの配列をhtmlに変換するだけ。

<?php
$data = range(1,50);

$params = array('perPage'=>10, 'itemData'=>$data);

$pager = new Pager($params);
foreach ($pager->getPageData() as $d) echo '<p>'.$d.'</p>';
echo '<hr>';
echo $pager;
?>
◎質問者からの返答

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

風邪を引いていたので、いただいたご回答を試すことができませんでした。

返事が遅れて済みません。


?の回答について

下記のようなエラーが出ました。

Warning: Unexpected character in input: ' in (中略)/Pager/Sliding.php on line 287


?の回答について

かなり手応えを感じています。ちょっと時間を加えればうまくいきそうです。

1ページ目に50件のデータが表示され、2ページ目に何もないという状態になっています。

また最初の1ページ目には「?id=1」と表示されません。


急いでお返事するために、あまり時間をかけて試してません。

いただいたご回答を元にもう少しがんばってみようとお思います。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ