元のデータは前と同じ 2to3nen.txt です。3年の名簿をソートして出るようにします。
3年の選択ボタンの部分はselect2.phpと同じですが、今回はselect3.phpというページにするのでactionの先も忘れずにselect3.phpに直します。その他は同じ。
<form action="select3.php#koko" method="post" id="koko" <p> <input type="submit" name="hr" value="2A"> <input type="submit" name="hr" value="2B"> <input type="submit" name="hr" value="2C"> <input type="submit" name="hr" value="2D"> <input type="submit" name="hr" value="2E"> <input type="submit" name="hr" value="2F"> <input type="submit" name="hr" value="2G"> <input type="submit" name="hr" value="2H"> </p> <p> <input type="submit" name="newhr" value="3A"> <input type="submit" name="newhr" value="3B"> <input type="submit" name="newhr" value="3C"> <input type="submit" name="newhr" value="3D"> <input type="submit" name="newhr" value="3E"> <input type="submit" name="newhr" value="3F"> <input type="submit" name="newhr" value="3G"> <input type="submit" name="newhr" value="3H"> </p> </form>
PHPプログラムはこちら。
まず、3年の時だけソートが必要なので、newhrに値が入っているかhrに値が入っているかで作業を分けます。 isset($_POST["hr"]) が hr に値が入っているかどうか調べる関数です。
newhrに値が入っているときには、sort.php でやった手法で、key,valを登録しています。今回のkeyはnewnoです。newhrで先に該当するデータだけに絞っているのがif ($newhr === $snewhr){の部分です。newhrで絞っているのでnewnoだけで順番が決まります。
$fp = fopen("2to3nen.txt","r"); $shr="2Z"; if( isset($_POST["hr"]) ){ $shr =$_POST["hr"]; while(!feof($fp)){ $line = fgets($fp); if (trim($line) != null){ list($hr,$no,$sei,$mei,$seib,$ysei,$ymei,$newhr,$newno) = explode("\t",$line); if ($hr === $shr){ print "<tr>\n"; print "<td>$hr</td><td>$no</td><td>$sei</td><td>$mei</td>"; print "<td>$seib</td><td>$ysei</td><td>$ymei</td>\n"; print "<td>$newhr</td><td>$newno</td>\n"; print "</tr>\n"; } } } } $snewhr="3Z"; if( isset($_POST["newhr"]) ){ $snewhr =$_POST["newhr"]; while(!feof($fp)){ $line = fgets($fp); if (trim($line) != null){ list($hr,$no,$sei,$mei,$seib,$ysei,$ymei,$newhr,$newno) = explode("\t",$line); if ($newhr === $snewhr){ $key = $newno; $val = $line; $gotoarray[$key]=$val; } } } ksort($gotoarray); foreach ($gotoarray as $key => $val) { list($hr,$no,$sei,$mei,$seib,$ysei,$ymei,$newhr,$newno) = explode("\t",$val); print "<tr>\n"; print "<td>$hr</td><td>$no</td><td>$sei</td><td>$mei</td>"; print "<td>$seib</td><td>$ysei</td><td>$ymei</td>\n"; print "<td>$newhr</td><td>$newno</td>\n"; print "</tr>\n"; } } fclose($fp);
残念ながら、上記のソートでは次のようになります。
これはksort($gotoarray);の並べ替えがデータを文字列として扱っている為です。
2E | 2 | 梅村 | 千草 | 女 | うめむら | ちぐさ | 3A | 1 |
2E | 11 | 諏訪 | 亜由香 | 女 | すわ | あゆか | 3A | 10 |
2D | 11 | 相馬 | 美和 | 女 | そうま | みわ | 3A | 11 |
2D | 12 | 竹浪 | 千秋 | 女 | たけなみ | ちあき | 3A | 12 |
2A | 14 | 鳴海 | 麻美 | 女 | なるみ | あさみ | 3A | 13 |
2F | 14 | 野呂 | 春菜 | 女 | のろ | はるな | 3A | 14 |
2C | 16 | 福田 | 初美 | 女 | ふくだ | はつみ | 3A | 15 |
2A | 15 | 蒔苗 | 菜摘 | 女 | まかなえ | なつみ | 3A | 16 |
2H | 16 | 山内 | 志保 | 女 | やまうち | しほ | 3A | 17 |
2C | 18 | 幸田 | 奈々子 | 女 | ゆきた | ななこ | 3A | 18 |
2D | 19 | 浅利 | 和哉 | 男 | あさり | かずや | 3A | 19 |
2A | 3 | 岡本 | 愛 | 女 | おかもと | あい | 3A | 2 |
2D | 21 | 石川 | 和茂 | 男 | いしかわ | かずしげ | 3A | 20 |
2B | 20 | 一戸 | 聡 | 男 | いちのへ | さとし | 3A | 21 |
.. | .. | .............. | .. | .. |
これはksortにSORT_NUMERICの指示を加えることで回避できます。ksort($gotoarray)をksort($gotoarray,SORT_NUMERIC)にしてください。
3年のクラスと番号を行の先頭に表示させるのは簡単です。print "<td>$hr</td><td>$no</td>...の部分を変更するだけです。
sort.php でksort()を紹介した関係で上記の方法が先になりましたが、今回の条件なら配列に代入するだけでソートを使うことなく実現できます。
c言語やjavaなど「整数の添字で記憶場所を指定する配列」に慣れているとわかりやすい手法です。しかし注意すべき問題もあります。以下3年の部分だけ示します。
$snewhr="3Z"; if( isset($_POST["newhr"]) ){ $snewhr =$_POST["newhr"]; while(!feof($fp)){ $line = fgets($fp); if (trim($line) != null){ list($hr,$no,$sei,$mei,$seib,$ysei,$ymei,$newhr,$newno) = explode("\t",$line); if ($newhr === $snewhr){ $gotoarray[(int)$newno]=$line; } } } $count = count($gotoarray); for ($i = 1; $count>=$i; $i++) { print "<tr>\n"; list($hr,$no,$sei,$mei,$seib,$ysei,$ymei,$newhr,$newno) = explode("\t",$gotoarray[$i]); print "<td>$hr</td><td>$no</td><td>$sei</td><td>$mei</td>"; print "<td>$seib</td><td>$ysei</td><td>$ymei</td>\n"; print "<td>$newhr</td><td>$newno</td>\n"; print "</tr>\n"; } }
(int)はキャストと呼ばれ、$newnoを文字列から整数に変換します。$newnoは$lineから切り取られたので文字列になっています。このままでは$newnoは文字列のままkeyになってしまいます。
forはc言語やjavaなどでよく使われる構文なのでforeachよりよく知られていますが、慣れていない人がforeachより分かりやすいかというと疑問です。
要素数を調べる count($gotoarray)は毎回データ数を数えるのであらかじめ別の変数に覚えさせます。これが添え字の最大値と必ずしも一致しないので問題があります。
たとえば、3Aの2番がデータから抜けていたとします。
2E | 2 | 梅村 | 千草 | 女 | うめむら | ちぐさ | 3A | 1 |
2B | 5 | 小野寺 | のぞみ | 女 | おのでら | のぞみ | 3A | 3 |
2G | 4 | 葛西 | 由佳 | 女 | かさい | ゆか | 3A | 4 |
2D | 5 | 樺沢 | 郁乃 | 女 | かばさわ | いくの | 3A | 5 |
.. | .. | .............. | .. | .. | ||||
2G | 34 | 福原 | 史学 | 男 | ふくはら | ふみのり | 3A | 34 |
2A | 31 | 藤田 | 健一 | 男 | ふじた | けんいち | 3A | 35 |
3Aの36番があるのですが、2番が抜けて35人分しかデータが無いので35までしか表示しません。2番のデータが無いので2番の所は空欄になっています。空欄になるのは好ましい場合もありますが、入っているデータが表示されないのは厄介です。
phpの配列の基本が「keyとvalueを関係付けるmap」であるため、key,valueを用いてforeachを使うほうがお勧めです。
上の説明は前回の課題2の解答になっています。
前回の課題2 select3.php を完成させなさい。index.htmlに「phpで選択3」という名前のリンクを作りましたか。