LoginSignup
22
23

More than 5 years have passed since last update.

【PHP】PDOで、複合検索+ページネーション

Last updated at Posted at 2015-09-13

お目汚し失礼いたします。
ど素人の勉強ノートです。今回は、複合検索にページネーションを付けてみました。
長いです……絶対、もっと短くなると思います。
何か問題などございましたら、ご指摘いただけると大変うれしいです。
よろしくお願いします!

複合検索+ページネーション

sample.php
<?php
// ページネーション 
const PER_PAGE = 10;// 1ページに表示するデータ数
$page = "";
if(empty($page)){
    $page = 1;
}
if(!empty($_GET['page'])){
    if(preg_match('/^[1-9][0-9]*$/', $_GET['page'])){
        $page = (int)$_GET['page'];
    } else {
    $page = "";
    }
}
$offset = PER_PAGE * ($page - 1);
echo $offset;
echo "/".PER_PAGE;


// 複合検索ワードの処理開始
$q = filter_input(INPUT_GET, 'q');
if(!empty($q)){
    $words = explode(" ", str_replace(" ", " ", trim($q)));
} else {
$words = array();
}
//
$tmp = array();
$arr = array();
foreach($words as $key=>$word){
    if($word === ''){ continue;}
    $tmp[$key] = sprintf('(keyword like :word%d)', $key);
    $arr[$key] ='%' . addcslashes($word, '\_%') . '%';
}
if (count($tmp) > 0){
    $pdo = getDb();
    $stmt = $pdo->prepare('SELECT * FROM tables WHERE '.implode('and', $tmp).' ORDER BY id desc LIMIT '.$offset.','.PER_PAGE);
    foreach($arr as $key=>$word){
        $stmt->bindValue(sprintf(':word%d', $key), $arr[$key], PDO::PARAM_STR);
    }// ここをbindParamにすると失敗します。
    $stmt->execute();
    $pdo = NULL;

// 検索された全データの数を求める
    $db = getDb();
    $stt = $db->prepare('SELECT * FROM tables WHERE '.implode('and', $tmp).' ORDER BY id desc');
    foreach ($arr as $key => $word) {
    $stt->bindParam(sprintf(':word%d', $key), $arr[$key], PDO::PARAM_STR);
}
    $stt->execute();
    $pdo = NULL;
    $resultSet = $stt->fetchAll();
    $total = count($resultSet);
    $totalPages = ceil($total / PER_PAGE);
    echo "totalpage:".$totalPages;


} else {// 検索ワードが挿入されなかった場合、すべてのデータをページ送りで出力する
$pdo = getDb();
$stmt = $pdo->prepare('SELECT * FROM tables ORDER BY id desc LIMIT '.$offset.','.PER_PAGE);
$stmt->execute();
    $pdo = NULL;
// 総数を出す
    $db = getDb();
    $stt = $db->prepare('SELECT * FROM tables ORDER BY id desc');
    $stt->execute();
    $pdo = NULL;
    $resultSet = $stt->fetchAll();
    $total = count($resultSet);
    $totalPages = ceil($total / PER_PAGE);
}
?>
<html>
<body>
// 検索窓を設置
        <form action="" method="GET">
        <input type="text" name="q" size="20"  value="<?php e($q); ?>">
        <input type="submit" value="search">
        </form>
// 結果をtableで出力
        <table>
            <tr>
                <th>セリフ</th>
                <th>作品タイトル</th>
                <th>キーワード</th>
                <th>編集</th>
            </tr>
                <?php while($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
                <?php printf('<tr><td>%s</td><td>%s</td><td>%s</td>', htmlspecialchars($row['title']), htmlspecialchars($row['author']), htmlspecialchars($row['keyword'])); ?>
                <td><a href="edit.php?id=<?php print(htmlspecialchars($row['id'])); ?>"></a></td></tr>
                <?php endwhile; ?>
            </tr>
        </table>
        <div>// ページリンク設定
            <?php if($page > 1): ?>
            <a href="?q=<?php if(!empty($q)){ echo $q; } ?>&page=<?php echo $page-1; ?>">前へ</a>
            <?php endif; ?>
            <?php for ($i = 1; $i <= $totalPages; $i++): ?>
                <?php if ($page == $i): ?>
                    <?php printf('%d', htmlspecialchars($i)); ?>
                <?php else: ?>
                    <?php printf('<a href="?q=%s&page=%d">%d</a>',htmlspecialchars($q), htmlspecialchars($i), htmlspecialchars($i)); ?>
                <?php endif; ?>
            <?php endfor; ?>
            <?php if($page < $totalPages): ?>
                <a href="?q=<?php if(!empty($q)){ echo $q; } ?>&page=<?php echo $page+1; ?>">次へ</a>
            <?php endif; ?>

参考

俺的PHPメモ
PHPでPDOを使ってAND検索(OR検索)を実装する
PHPで作るページング機能

課題

長いこと……重複が見られるので、もっと短くできる、はず。
あとはPDO周りが不安なこと。prepareに変数を入れてはダメだという記事を読んでから、直で入れるようにしましたが、検索ワードをこのように突っ込んでも平気なのか、と。

22
23
9

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
23