phpの勉強をしています。

ある配列の要素を5件ずつ表示させる方法を考えています。
検索サイトなどによくある感じで現在のページ以外を参照するには
要素数を5で割ったリンクが必要です。

//ここに要素が5つ(最後のページは5の余り数)

//移動のためのリンク
1|2|3|4|5|6|...

思いつきで以下のように書いてみましたが、
どうも続きがうまくいきません。よろしくお願いします。

$result = array();
$x = 0;
for($i=0;$i<count($fl_array);$i++){
$result[$x][] = $fl_array[$i];
if ($i % 5 == 4) {
$x++;
}
}

for($i=1;$i<=count($result);$i++){
print "$i|";
}

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2009/05/01 01:06:50
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:kn1967 No.3

回答回数2915ベストアンサー獲得回数301

ポイント100pt

(3)新しいページ(リンク先)の処理の仕組み


今作っているページを

http://www.example.com/a.php

だとしますと

http://www.example.com/a.php?pg=1

というようにページ番号を受け取るようにします。

(ページ番号がなければゼロとします)

$p = 0;

という1行を

if(isset($_GET['pg'])){
    $p = $_GET['pg'] - 1;
} else {
    $p = 0;
}

に書き換えます。


※セキュリティ上、本当はpgの値を検証したり、どこからアクセスされたのかを検証したりしなくてはならず

そもそもGETではなくPOSTが・・・などなど非常に話が長くなるので今回は割愛します。


(4)リンクをつける


$result_keys = array_keys($result);
print join("|", $result_keys);

print "<br />\n";
$result_keys = array_keys($result);
$result_keys_count = count($result_keys);
for($i=0; $i<$result_keys_count; $i++){
    if ($i <> $p) {
        $result_keys[$i] = '<a href="a.php?p=' . $result_keys[$i] . '">' . $result_keys[$i] . '</a>';
    }
}
print join("|", $result_keys);

に変えます。一応、改行も入れときました。


※シングルクォーテーションで囲んだものは展開されませんので

¥でエスケープする必要がありません。

ダブルクォーテーションを使った場合は下記のようになりますが

複雑になってくると、どこがどこやら判りにくくなる場合もありますので

適宜使い分ける必要があります。

$result_keys[$i] = "<a href=\"a.php?p=$result_keys[$i]\">$result_keys[$i]</a>";

※a.php と書くのではなく SCRIPT_NAME という環境変数を利用する手があるのですが

こちらも話がさらに膨らみますので今回は割愛します。

# 実は、いまやろうとなさっていることを正確かつ安全に行おうとすれば

# 本が一冊書けたりするような内容なのですよね・・・。

その他の回答2件)

id:kn1967 No.1

回答回数2915ベストアンサー獲得回数301

ポイント100pt
# てすと用データ準備
$fl_array = array(1,2,3,4,5,6,7,8,9,10,11,12);

# 配列に格納
$result = array();
$x = 0;
$fl_count = count($fl_array);
for($i=0; $i<$fl_count; $i++){
    $result[$x][] = $fl_array[$i];
    if ($i % 5 == 4) {
        $x++;
    }
}

# 格納したデータの確認用表示
print_r($result);
print "<br />\n";

# 表示
$p = 1;
$result_count = count($result[$p]);
print $result[$p][0];
for($i=1; $i<$result_count; $i++){
    print "|" . $result[$p][$i];
}

(1)前半部分

・forが一巡する度にcountしなおすのは効率悪いので変数 $fl_count 追加。


(2)後半部分

・欲しいページ用に変数 $p 追加。

・X = 0 なので2ページ目が欲しいとすれば 1 とする。

・forが一巡する度に・・・で $result_count 追加。

・余計な|が入らないようにするため先頭だけループ外に変更。


(2改)後半部分の改造

・|で結合するだけであればループしなくてもjoinという手もある。

# 表示する。
$p = 1;
print join('|', $result[$p]);

既にご存知かもしれませんが

  print_r(配列変数);

はよく使いますので覚えておいてください。

上記であればブラウザには

Array ( [0] => Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 ) [1] => Array ( [0] => 6 [1] => 7 [2] => 8 [3] => 9 [4] => 10 ) [2] => Array ( [0] => 11 [1] => 12 ) ) 
6|7|8|9|10

と表示されますが、ソースを表示させれば以下のようになっているはずです。

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
            [4] => 5
        )

    [1] => Array
        (
            [0] => 6
            [1] => 7
            [2] => 8
            [3] => 9
            [4] => 10
        )

    [2] => Array
        (
            [0] => 11
            [1] => 12
        )

)
<br />
6|7|8|9|10
id:tontonpokopoko

回答をありがとうございました。

表示の仕方で悩んでいましたが

変数作り、$result[$p][0];と並べてやればいいんですね。

参考になりました!

2009/04/28 11:31:47
id:taichino0730 No.2

回答回数2ベストアンサー獲得回数1

ポイント50pt

実際はデータベース等と連携がありますので、

もう少し複雑になりますが、該当処理を書いてみました。


ページ数が増えた時の事を考えると、

現在のページの要素だけを抜き出すのも良いかもしれません。


少しややこしいのは件数からページ数の計算でしょうか。

要素数がページあたりの件数で割り切れるかどうかを考える必要があります。

ceil関数を使用すると簡単にかけますね。


あと、個人的にはプログラム上のページ番号は0からなのに、

ユーザインターフェース的には1からという事が合わさって妙に

デバッグに手間取った事があります。

#!/usr/bin/php
<?php
/**
 * Usage:
 *   count_array.php (ページ番号)
 */

# ページ番号は0基準か1基準か
$base = 0;# $base = 1;
# 表示するページをコマンドラインから取得
$current = $argv[1] - $base;

# 検索結果のリンク
$links   = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','z','y','z');
$linkNum = count($links);
# ページごとの要素数
$count = 5;
# ページ数を計算
$pages = ceil($linkNum / $count);

# 現在のページを表示
$start = $current * $count;
$end   = $start   + $count;
for ($i = $start; $i < $end; $i++) {
  if (isset($links[$i])) {
	print "<td> {$links[$i]} </td>" . "\n";
  }
}

# 他のページへのリンクを表示
$start = $base;
$end   = $base + $pages;
for ($i = $start; $i < $end; $i++) {
  print "<a>$i</a> ";
}
?>

キーワードとしては「ページング、php」等で検索すると

参考情報がたくさんヒットするようです。

id:tontonpokopoko

taichino0730さま、回答をありがとうございます。

コマンドラインの理解が難しいですが、

残りの処理はとても参考になります。

またページングという言葉のヒントを教えてもらって感謝です。

(私なりにかなり調べた後の質問だったのですが、”ページング”と言う言葉がわかりませんでした)

ページング検索で優しい説明のものもあったので、

1つ1つ試していきたいと思います。

2009/04/28 11:41:11
id:kn1967 No.3

回答回数2915ベストアンサー獲得回数301ここでベストアンサー

ポイント100pt

(3)新しいページ(リンク先)の処理の仕組み


今作っているページを

http://www.example.com/a.php

だとしますと

http://www.example.com/a.php?pg=1

というようにページ番号を受け取るようにします。

(ページ番号がなければゼロとします)

$p = 0;

という1行を

if(isset($_GET['pg'])){
    $p = $_GET['pg'] - 1;
} else {
    $p = 0;
}

に書き換えます。


※セキュリティ上、本当はpgの値を検証したり、どこからアクセスされたのかを検証したりしなくてはならず

そもそもGETではなくPOSTが・・・などなど非常に話が長くなるので今回は割愛します。


(4)リンクをつける


$result_keys = array_keys($result);
print join("|", $result_keys);

print "<br />\n";
$result_keys = array_keys($result);
$result_keys_count = count($result_keys);
for($i=0; $i<$result_keys_count; $i++){
    if ($i <> $p) {
        $result_keys[$i] = '<a href="a.php?p=' . $result_keys[$i] . '">' . $result_keys[$i] . '</a>';
    }
}
print join("|", $result_keys);

に変えます。一応、改行も入れときました。


※シングルクォーテーションで囲んだものは展開されませんので

¥でエスケープする必要がありません。

ダブルクォーテーションを使った場合は下記のようになりますが

複雑になってくると、どこがどこやら判りにくくなる場合もありますので

適宜使い分ける必要があります。

$result_keys[$i] = "<a href=\"a.php?p=$result_keys[$i]\">$result_keys[$i]</a>";

※a.php と書くのではなく SCRIPT_NAME という環境変数を利用する手があるのですが

こちらも話がさらに膨らみますので今回は割愛します。

# 実は、いまやろうとなさっていることを正確かつ安全に行おうとすれば

# 本が一冊書けたりするような内容なのですよね・・・。

  • id:kn1967
    回答は
    >//ここに要素が5つ(最後のページは5の余り数)
    までの分です。

    >//移動のためのリンク
    >1|2|3|4|5|6|...
    については
    $result_keys = array_keys($result);
    print join("|", $result_keys);
    という2行を追加すれば対応できます。
    もちろん、これは一行にまとめてもかまいませんし、ループ処理しても結構です。

    この二行を追加して思ったのですが
    X = 1;
    のほうが良くないですか?
  • id:tontonpokopoko
    kn1967さま、いつもありがとうございます。
    ただいま動作確認中です。
    1つ1つ違うことなども試しているため時間がかかってしまいます。
    申し訳ありません。m()m
  • id:kn1967
    こちらは全然かまいませんというか・・・
    途中で寝るかもしれませんので早い応答を期待されるほうが困ったりします(苦笑)
  • id:tontonpokopoko
    $result_keys = array_keys($result);
    print join("|", $result_keys);

    を追加すると表示部分が一緒になり
    以下になってしまっています。(p=0のケース)

    1|20|1|2|30|1|2|40|1|2|50|1|2

    と思いましたがfor文の中に書いてたためのミスでした。
    すいません。(追記)
  • id:tontonpokopoko
    現状はリンクの箇所がゼロから始まっていて、
    0|1|2

    "1"や"2"にリンクをつける場合どうなるのでしょうか?
    print ("<a href=\"");
    print ("ここがさっぱりです");
    print ("\">");

    また新しいページ(リンク先)の処理の仕組みがわかりません。
    よろしくお願いいたします。
  • id:kn1967
    リンクの話は本当は別質問としていただきたいほどの内容なのですが・・・
    とりあえず長くて見づらくなるので回答として投稿させていただきました。

    スミマセンが今日は寝ます・・・。
  • id:tontonpokopoko
    kn1967さま,おはようございます。
    ページングの質問をコメント欄でしてしまって申し訳ありません。
    上記の回答の方がご指摘の後「ページング」と検索してみて、
    その内容の難しさに、数回に分けて質問すべきだったと反省しております。

    何はともあれ、
    お時間をかけてお答えをいただき本当にありがとうございます。
    1つずつ試してみたいと思います。
    時間がかかるかもしれませんが、
    後ほど進行具合と、
    また解答欄などにもコメントをつけさせていただきます。
  • id:tontonpokopoko
    http://www.usamimi.info/~ryouchi/pager/?show=source

    上記のURLにかなり完成品に近いものがあり、また説明も詳しく掲載されていました。
    現状は配列を検索形式に変えていて、
    配列の要素をどうやってページ毎に変更させるか考えています。
    いい案があればよろしくお願いしますm()m

    (例えば3ページ目にジャンプしたときに、配列の11~15を表示させる方法です)
  • id:kn1967
    「配列を検索形式に変えて」とは具体的にどのように変えたのでしょう・・・。

    MySQLなどのデータベースを使っているならLIMIT句などでデータを制限して取得して
    配列に入れても良いし、直接表示とかさせても良いし・・・
    配列に入れたなら、私が回答した内容を理解してくださっていれば出来るはずですけど・・・

    理解しやすさを考慮して、出来る限り横道にそれないように、でも、
    必要と思われる情報は出来る限り加えて、お答えするようにしているのですが・・・

    私の2回目の回答分を実行しておられない、またはご理解いただけてないのか
    それとも放置されているのか判りませんが、身に付けたいのではなく
    早急に作りたいという方向に走りすぎている感じがします。

    お示しになった先にあるプログラムの基礎的部分は私の回答したものに含まれていますので
    まずは、私の回答した分だけでもきっちりと身に付けてくださいませ。
  • id:tontonpokopoko
    kn1967さま,
    2回目の回答文は実行済みで、現在もいろいろと試している段階です。
    やりたかったことはデータベースからの検索ではなく、
    あるグループにID化されたディレクトリ上の
    イメージファイルを検索($pattern)して取り出す勉強でした。
    後々XMLファイルを作成するかしてAJAXを考えていますが、
    まずはPHPでその仕組みを理解しようとしている次第です。

    ページングのほうで本来の質問とズレてしまい大変申し訳ありませんでした。
    参考にさせてもらい勉強させていただきます。

    # $filedir='/virtual/test/public_html/image';#取得したいディレクトリ
    # $dirlist=array();#格納先の配列を準備
    # $strDir=opendir($filedir);#ディレクトリを開く
    # while($str=readdir($strDir)){array_push($dirlist,$str);}#1つづつ配列に格納
    # closedir($strDir);#ディレクトリを閉じる
    # print ("<hr>\n");
    # var_dump($result);
    # $pattern = '(gif)';
    # $fl_array = array_values(preg_grep ($pattern,$dirlist));
  • id:kn1967
    preg_シリーズのパターンの部分は
    perl互換の正規表現であらわさなければならないので
      $pattern = '/^.+\.gif$/i';
    といった具合になります。

    これまた新しい話なので
    正規表現は別途学んでいただくとしてアバウトに
      ^ 先頭から
      .+ すべての文字
      \. ピリオド
      gif$ gifで終わる事
      i 大文字小文字を同じと扱う

    ファイルオープンの時点で失敗している可能性も考慮すると
    $filedir='/image';
    $dirlist=array();
    if($strDir = opendir($filedir)) {
      while(false !== ($str = readdir($strDir))){
        array_push($dirlist, $str);
      }
      closedir($strDir);
    } else {
      print "ディレクトリを開けませんでした\n";
    }
    print ("<hr>\n");
    var_dump($result);
    $pattern = '/^.+\.gif$/i';
    $fl_array = array_values(preg_grep($pattern, $dirlist));
    ※これは動作確認せずに回答してます。
    ※インデントは全角スペースです。ご注意を。
  • id:kn1967
    gif と jpeg と png に対応させたい場合
      $pattern = '/^.+\.(gif|jpeg|png)$/i';

    画像ファイル名ではなく画像を表示させる場合
      回答2の4を参考に
      回答1の「# 表示」以下の部分を改造してください。
  • id:tontonpokopoko
    kn1967さま,
    何度もありがとうございます。正常に動作しています。
    正規表現の修正も参考になりました。
    画像は以下のようにタグを付け足して表示させることは
    今回の質問前から出来たのですが、
    まだ5件ずつそれを表示させる方法がわかりません。
    「p」でページを指定(例えば3ページ目で要素10~15)した後に、
    もう1度表示させたページから移動した場合がわからないのです。
    もう少し試してみますがヒントがあればお願いいたします。

    print_r($fl_array);#配列を表示
    print ("<hr>\n");
    while(list ($key, $val) = each($fl_array)) {
    print ("<img src=\"");
    print ("../image/$val");
    print ("\">");
    print ("<br>\n");


    *18:05:28のコメントはまだ動作確認していません。
  • id:kn1967
    #表示 の部分だけではなく回答1および回答3で行った改造すべてを含んだ上で
    $fl_array = array(1,2,3,4,5,6,7,8,9,10,11,12);
    を 2009-04-28 17:44:07 のコメントで書いたコードに置き換えるのですよ。

    それが済んでから、#表示 の部分でIMGタグをつけるんです。

    1日程度で理解しろというほうが難しいのかもしれませんが
    順番どおりに増改築していけば完成するように順を追って回答してありますから、
    あせらず、おさらいしてみてくださいね。
  • id:tontonpokopoko
    いろいろとありがとうございます。
    単純な作業でも見落としなどがあるため、もどかしい思いです。
    (教えてくれる側は何倍ももどかしいでしょうけど・・)
    が、何とか1つずつ理解したいと思います。
    少し時間をとられるので、また夜中に試させていただきます。
    とりあえず報告まで。
  • id:tontonpokopoko
    こんにちは。
    初期ページでは教えてもらった方法で画像が5件ずつ表示されますが、
    やはり「a.php?p=1」から「a.php?p=2」にジャンプしようとすると
    URL自体は変化していますが表示内容は変わりません。
    (リンク部分も最初のページのままです)

    もう少しいろいろ試してみます。
  • id:kn1967
    ※ 動作確認していないけど、これまでの流れをまとめると以下のような感じです。
    ※ 動作検証も含めて、ご自身のコードと見比べてください。
    ※ 何度も申し訳ないですがインデントは全角スペースです。半角に置換してください。

    <?php
    # データ準備(ファイル検索)
    $filedir='/image';
    $dirlist=array();
    if($strDir = opendir($filedir)) {
      while(false !== ($str = readdir($strDir))){
        array_push($dirlist, $str);
      }
      closedir($strDir);
    } else {
      print "ディレクトリを開けませんでした\n";
    }
    var_dump($dirlist); # 確認用出力
    print ("<hr>\n");

    # データ準備(画像ファイルだけ抽出)
    $pattern = '/^.+\.gif$/i';
    $fl_array = array_values(preg_grep($pattern, $dirlist));
    var_dump($dirlist); # 確認用出力
    print ("<hr>\n");

    # 配列に格納
    $result = array();
    $x = 0;
    $fl_count = count($fl_array);
    for($i=0; $i<$fl_count; $i++){
      $result[$x][] = $fl_array[$i];
      if ($i % 5 == 4) {
        $x++;
      }
    }
    var_dump($result); # 確認用出力
    print ("<hr>\n");

    # ページ番号受け取り
    if(isset($_GET['pg'])){
      $p = $_GET['pg'] - 1;
    } else {
      $p = 0;
    }

    # 表示(画像)
    $result_count = count($result[$p]);
    for($i=0; $i<$result_count; $i++){
      print '<img src="/image/' . $result[$p][$i] . "\"><br>\n";
    }

    print ("<hr>\n"); # 区切り

    # 表示(リンク)
    $result_keys = array_keys($result);
    $result_keys_count = count($result_keys);
    for($i=0; $i<$result_keys_count; $i++){
      if ($i <> $p) {
        $result_keys[$i] = '<a href="a.php?p=' . $result_keys[$i] . '">' . $result_keys[$i] . '</a>';
      }
    }
    print join("|", $result_keys);
    ?>
  • id:tontonpokopoko
    何度もありがとうございます。
    以下のソースで同じだと思うのですが、
    どこかおかしいでしょうか?
    (imageだけパスを自分のものと変更しています)


    <?php

    # データ準備(ファイル検索)
    $filedir='/image';
    $dirlist=array();
    if($strDir = opendir($filedir)){
    while(false !== ($str = readdir($strDir))){
    array_push($dirlist, $str);
    }
    closedir($strDir);
    } else {
    print "ディレクトリを開けませんでした\n";
    }

    var_dump($dirlist); # 確認用出力
    print ("<hr>\n");

    $pattern = '/^.+\.gif$/i';
    $fl_array = array_values(preg_grep($pattern, $dirlist));

    var_dump($dirlist); # 確認用出力
    print ("<hr>\n");

    # 配列に格納
    $result = array();
    $x = 0;
    $fl_count = count($fl_array);
    for($i=0; $i<$fl_count; $i++){
    $result[$x][] = $fl_array[$i];
    if ($i % 5 == 4) {
    $x++;
    }
    }

    var_dump($dirlist); # 確認用出力
    print ("<hr>\n");

    # 表示
    if(isset($_GET['pg'])){
    $p = $_GET['pg'] - 1;
    } else {
    $p = 0;
    }

    $result_count = count($result[$p]);

    for($i=0; $i<$result_count; $i++){
    print ("<img src=\"image/");
    print ($result[$p][$i]);
    print ("\">");
    }

    print "<br />\n";

    $result_keys = array_keys($result);
    $result_keys_count = count($result_keys);
    for($i=0; $i<$result_keys_count; $i++){
    if ($i <> $p) {
    $result_keys[$i] = '<a href="test2.php?p='.$result_keys[$i].'">'.$result_keys[$i].'</a>';
    }
    }
    print join("|", $result_keys);

    ?>

  • id:kn1967
    私のコピペがミスってました。

    受け取る変数は
      if(isset($_GET['pg'])){
    ということで
    pg
    なのに対して、リクエストを送る段階の
      $result_keys[$i] = '<a href="test2.php?p='.$result_keys[$i].'">'.$result_keys[$i].'</a>';
    では
     p
    を送っている・・・。
  • id:tontonpokopoko
    php?pgとしてみましたが、
    画像の結果が1ページずれているみたいです・・
    ちょっと試してみます。
  • id:tontonpokopoko
    kn1967さま,
    いろいろとお付き合いいただきありがとうございました!
    http://oshiete1.goo.ne.jp/qa2110551.html
    こちらを参考にpgをidに書き換えることで正常に動作いたしました。

    かなり悩んで時間がかかりましたが、今後も1つずつ覚えていこうと思います。
    長い時間、親切に教えてもらって心から感謝いたします。

    こちらでこの質問は終了いたしますが、
    最後に今の疑問を1つだけ、

    "$pattern"にフォームから送られてきた"elem"で、
    gifを検索するところまでは出来ているのですが、
    この場合ですと、初期ページはうまく表示されるのですが、
    ページを移行すると画像がすべて消えてしまいます。
    (また検索すれば初期ページは表示される状態)

    <form method="get" action="<?php echo $SCRIPT_NAME ?>">
    <input type="radio" name="elem" value="gif" checked>gif
    <input type="submit" value="検索">
    </form>

    もしよろしければ助言をいただければ幸いです。
    少ししてコメントもなく疑問が取れなかったら、
    また新たに"はてな"で質問したいと思います。

    今後もどうぞよろしくお願いいたします。
  • id:kn1967
    >画像の結果が1ページずれている

    検証はいたしませんが、糸口としては
    「ページは1からなのに、配列がゼロから始まる」という点。
    -1 が不要?

    >pgをidに書き換えることで正常に動作いたしました。

    他の方法に切り替えることは悪いことではありませんが
    原因を究明せずに他に逃げたとも言えなくもありませんので
    学習が主目的であるという現状からは・・・。

    >初期ページはうまく表示されるのですが、
    >ページを移行すると画像がすべて消えてしまいます。

    今現在の構造が見えませんが
    処理の流れと、それぞれの箇所で必要な変数、そして変数の値について
    順を追って見直していくと直ると思いますよ。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません