こんにちは。この度も、宜しくお願いします。
http_build_queryの使い方の理解が及ばず、ページ送りをうまく実装できません。
以下のような、詳細検索ページを作りたいと考えています。
キーワードandスタイルand(メディアorメディア)のような検索方法です。
色々なサイトさまを参考に、検索まではできるようになったのですが、
ページ送りを実装して、次のページへ行くと、チェックボックスやラジオボックスの検索内容を維持できません。
以下のままですと、チェックボックスはurlに「&m[0]=anime&m[1]=comic」と記されてしまいます。
どうしたら「&m=anime&m=comic」のようにできますでしょうか。
または、ページ送りをきちんとできるようになりますでしょうか。
よろしくご指導ください。お忙しい中、大変恐縮ではございますが、お願いします。
<?php
/* htmlspecialchars のラッパーを定義 */
function h($str) {
return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}
/* 設定 */
$config = [
'pdo' => [
// SQL_CALC_FOUND_ROWS を利用するのでMySQL前提
'dsn' => 'mysql:dbname=****;host=localhost;charset=utf8',
'username' => '****',
'password' => '****',
],
'pagenation' => [
'per_page' => 3,
],
];
$mediaform = array('anime' => 'アニメ','comic' => 'コミック','novel' => '小説','game' => 'ゲーム','cinema' => '映画');
$word_styleform = array('word' =>'セリフ','style' => '地の文');
/* GETパラメータを変数にセット(ページ表示時に再利用してもよい) */
$request = [
'page' => max((int)filter_input(INPUT_GET, 'page'), 1), // 1以上の整数を保証
'q' => (string)filter_input(INPUT_GET, 'q'), // 文字列を保証
'm' => filter_input ( INPUT_GET,'media', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY),
];
/* データベースに接続 */
try {
// PDOインスタンスを準備
$c = $config['pdo'];
$pdo = new PDO($c['dsn'], $c['username'], $c['password']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
// 全角スペースなども含めて全てを「1バイト以上の文字列」に分割する
$words = preg_split(
"/[\\x0-\x20\x7f\xc2\xa0\xe3\x80\x80]++/u",
$request['q'],
-1,
PREG_SPLIT_NO_EMPTY
);
$media = filter_input ( INPUT_GET,'media', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
$word_style = (string)filter_input(INPUT_GET, 'word_style');
$test = "";
if (!empty($media)){
foreach($media as $check){
$ttt[] = "Find_IN_SET('$check',media)";
}
$test = implode(' or ', $ttt);
$test2 = " ( ".$test . ")";
}
$radio = "";
if (!empty($word_style)){
$radio = sprintf (' word_style = \'%s\'', $word_style);
}
if(!empty($word_style)){
if(!empty($media)){
$msw = " AND ".$radio." AND ".$test2;
} else {
$msw = " AND ".$radio;
}
} elseif(!empty($test2)) {
$msw = " AND ".$test2;
} else {
$msw = "";
}
// 検索を実行
$conds = ['1'];
$values = [];
foreach ($words as $word) {
$conds[] = 'keyword LIKE ? ESCAPE "!"';
$values[] = '%' . preg_replace('/(?=[!_%])/', '!', $word) . '%';
}
$format = 'SELECT SQL_CALC_FOUND_ROWS id,word,keyword FROM ttables WHERE %s %s ORDER BY id DESC LIMIT %d, %d';
$stmt = $pdo->prepare(sprintf(
$format,
implode(' AND ', $conds),
$msw,
$config['pagenation']['per_page'] * ($request['page'] - 1),
$config['pagenation']['per_page']
));
$stmt->execute($values);
// 結果とページネーションのための情報を取得
$rows = $stmt->fetchAll();
$page_count = ceil(
(int)$pdo->query('SELECT FOUND_ROWS()')->fetchColumn()
/ $config['pagenation']['per_page']
);
} catch (PDOException $e) {
$error = $e->getMessage();
}
/* UTF-8のHTML文書であることをブラウザに明示する */
header('Content-Type: text/html; charset=UTF-8');
?>
</body> </html><body>
<h2>詳細検索</h2>
<div>
<form action="" method="get">
<div>
<label for="q">キーワード:</label>
<input type="text" name="q" size="25" value="<?=h($request['q'])?>">
</div>
<div>
<label for="word_style">スタイル:</label>
<input type="radio" name="word_style" value="word" />セリフ
<input type="radio" name="word_style" value="style" />地の文
</div>
<div>
<label for="media">メディア:</label>
<?php
foreach($mediaform as $key =>$val){
if(!empty($media)){
$kekka = array_search($key, $media);
if($kekka === false){
$chk = "";
} else {
$chk = "checked";
}
}
echo "<input type=\"checkbox\" name=\"media[]\" value=\"";
echo $key. "\"";
if(!empty($chk)){echo $chk;}
echo ">";
echo $val;
}
?>
</div>
<div>
<input value="検索開始" type="submit" />
</div>
</form>
</div>
<!-- エラーがあれば出力 -->
<?php if (isset($error)): ?>
<p><?=h($error)?></p>
<?php endif; ?>
<!-- 結果があれば出力 -->
<?php if (!empty($rows)): ?>
<table>
<tr>
<th>作品タイトル</th>
<th>キーワード</th>
<th>編集</th>
</tr>
<?php foreach ($rows as $row): ?>
<tr>
<td><?=sprintf('<a href="data.php?id=%d">%s</a>', $row['id'], h($row['word'])) ?></td>
<td><?=h($row['keyword'])?></td>
<td><?=sprintf('<a href="edit.php?id=%d">◆</a>', $row['id'])?></td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<!-- ページネーション -->
<?php
if (isset($page_count)) {
// 表示内容を配列に格納する
$items = [];
// 2ページ目以降であれば「前へ」をセット
if ($request['page'] >= 2) {
$items[] = sprintf('<a href="?%s">前へ</a>', http_build_query([
'page' => $request['page'] - 1,
'q' => $request['q'],
'm' => $request['m']
], '', '&'));
}
// ページ番号をセット
for ($i = 1; $i <= $page_count; ++$i) {
if ($i === $request['page']) {
$items[] = "$i";
} else {
$items[] = sprintf('<a href="?%s">%d</a>', http_build_query([
'page' => $i,
'q' => $request['q'],
'm' => $request['m']
], '', '&'), $i);
}
}
// 次のページがあれば「次へ」をセット
if ($request['page'] <= $page_count - 1) {
$items[] = sprintf('<a href="?%s">次へ</a>', http_build_query([
'page' => $request['page'] + 1,
'q' => $request['q'],
'm' => $request['m']
], '', '&'));
}
// 表示
echo '<div>' . implode(' | ', $items) . '</div>';
}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。