昨日からのお題。
英単語テーブル「words」を検索するページを作る。
ページャー付きでモリッと作ったのでコードをドーンッ!
目次
検索ページを作る
コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
<?php require_once '../php_include/Encode.php';// 文字エンコード用のファイル require_once '../php_include/db_connect.php';// DBテーブル読み込み用ファイル $db = getDB();//db_connect.phpで定義したPDOオブジェクトを返す関数 // 検索パターンの配列 $types = array( 'begin' => 'から始まる', 'part' => 'を含む', 'end' => 'で終わる', 'perf' => 'と一致する' ); // 検索語 $word = $_GET['word']; if ($_GET['type'] == 'begin') { $word = $_GET['word'].'%'; $type = $types['begin']; } elseif ($_GET['type'] == 'part') { $word = '%'.$_GET['word'].'%'; $type = $types['part']; } elseif ($_GET['type'] == 'end') { $word = '%'.$_GET['word']; $type = $types['end']; } else { $word = $_GET['word']; $type = $types['perf']; } // テーブル検索 $stt = $db->prepare('SELECT * FROM words WHERE title LIKE (:title)'); $stt->bindValue(':title', $word); $stt->execute(); // ページ数チェック if (preg_match('/^[1-9][0-9]*$/', $_GET['page'])) { $page = (int)$_GET['page']; } else { $page = 1; // 不正な値は全て1ページ目にする } // ページャー生成 const WORDS_PER_PAGE = 20; // 1ページあたり表示件数指定 $result = $stt->fetchAll(); // 検索結果の配列 // $total = $stt->rowCount(); // fetchしてarray_pushしてた時のためらい傷。fetchAllに変えたので要らなくなった。そもそもarray_pushしたものをcountすればcountで良かった。 $total = count($result); $totalPages = ceil($total / WORDS_PER_PAGE); $offset = WORDS_PER_PAGE * ($page - 1); // 開始件数 $from = $offset + 1; $to = ($offset + WORDS_PER_PAGE) < $total ? ($offset + WORDS_PER_PAGE) : $total; ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>検索</title> </head> <body> <h1>英単語検索</h1> <div id="search_box"> <p>検索語を入力して検索ボタンを押してください。</p> <form action="" method="get"> <div> <label for="word">検索語:</label> <input type="text" name="word" value="<?php echo e($_GET['word']); ?>"> <?php foreach ($types as $key => $value): ?> <input type="radio" name="type" value="<?php echo $key; ?>" <?php if ($key == $_GET['type']) { echo ' checked'; } ?>><?php echo $value; ?> <?php endforeach; ?> </div> <input type="submit" value="検索"> </form> </div> <?php if ($_GET != NULL): ?> <div id="result_box"> <h2><?php print('"'.e($_GET['word']).'" '.$type); ?>単語</h2> <p>検索結果:全<b><?php echo $total; ?></b>件中 <b><?php echo $from; ?></b>件~<b><?php echo $to; ?></b>件を表示</p> <table border="solid 1px #FFFFFF"> <tr> <th>ID</th> <th>単語</th> <th>意味</th> </tr> <?php for ($i=$offset; $i < $to; $i++): ?> <tr> <td><?php echo e($result[$i]['word_id']); ?></td> <td><?php echo e($result[$i]['title']); ?></td> <td><?php echo e($result[$i]['body']); ?></td> </tr> <?php endfor; ?> </table> <div id="pager"> <?php if ($page > 1): ?> <a href="?word=<?php echo e($_GET['word']); ?>&type=<?php echo e($_GET['type']); ?>&page=<?php echo $page-1; ?>">前</a> <?php endif; ?> <?php for ($i=1; $i <= $totalPages; $i++): ?> <?php if ($page == $i): ?> <b><?php echo $i; ?></b> <?php else: ?> <a href="?word=<?php echo e($_GET['word']); ?>&type=<?php echo e($_GET['type']); ?>&page=<?php echo $i; ?>"><?php echo $i; ?></a> <?php endif; ?> <?php endfor; ?> <?php if ($page < $totalPages): ?> <a href="?word=<?php echo e($_GET['word']); ?>&type=<?php echo e($_GET['type']); ?>&page=<?php echo $page+1; ?>">次</a> <?php endif; ?> </div> <?php endif; ?> </div> </body> </html> |
ページャーリンクにクエリパラメータを渡して、
(そのページの値-1) × 20件目から20件分配列の要素を取り出す処理をしている。
表示
const
定数を定義する。
本来はクラス定数を定義するものだったが、PHP5.3.0以降ではクラス外で定義できるようになった。
詳しくはマニュアルの構文の項目で。
今回は1ページに表示する件数を定数とした。
PDOStatement::fetchAll
全ての結果行を含む配列を返す。
結果セットをそのまま配列に入れたい場合などに使える。
SQL文を二回発行(レコード数、ページに表示する20行だけのレコード)したくなかったので一度全部配列に詰めている。
PDOStatement::rowCount
直近のSQLステートメントによって作用した行数を返す。
今回は検索結果の結果セットの行数(ヒットした数)を取らせるつもりだったが配列に詰めてるしcountでいけるやん・・・・ということでコメントアウト。
ceil
端数の切り上げ。数学関数の一つ。
今回はページ数を割り出すのに少数になったり切り捨てになったりで最終ページが表示されない状態にならないために使った。
echoとprint
文字列を出力するという点においては差は無い。
好き好きなんて言う話もあったりする。
ただ挙動が違うのでここで一回押さえておこうと思う。
echoの特徴
一つ以上の文字列を出力する。
カンマ区切りで複数の文字列を出力できる(ただし括弧を使うと複数指定できない)
返り値が無い(printよりわずかに速い)
printの特徴
文字列を出力する。
複数の文字列は出力できない(ただしピリオドによる文字列連結は出来る)
返り値がある、常に1を返す(この処理でechoよりわずかに遅い)
こちらの記事「あなたは『echo』派?それとも『print』派?」 – ht79.infoではPerlにはechoが無かったはずだから昔からそういう言語に触れている人はprintが多いのでは?と言及しています。
こちらの記事「PHPのechoとprintの違い」 – FLAMA技術Blogでは詳しい挙動の差に触れながらprintを個人的におすすめしていると語られています。
やはり好みが大きい感じもしますが、
大規模な処理が行われる場合のことも考えると個人的にはechoを使うべきなのか?とも思いますが、もっと根本的な処理を改善すべきじゃね?と考えればechoじゃなければならない!って感じでもないです。
括弧のくくりやすさで見通しが良くなりそうなprintも個人的には好きですし。(と言うか調べるまでprintオンリーでええやろって思ってた)
とにかく制作単位(プロジェクト、個人)でルールを設けて見通しを良くするのが良さそうですね。
今日のひとこと
dropboxに昨日の日付のフォルダが無いんですけど昨日はやらなかったんですか?
んなわけあるか・・・・
コメント
No Trackbacks.