【问题标题】:combining search with pagination not outputting correctly将搜索与分页相结合未正确输出
【发布时间】:2016-09-17 09:18:11
【问题描述】:

目前,分页功能在显示所有结果时运行良好,或者如果我操纵查询以显示特定结果(WHERE X = Y),我可以愉快地循环浏览所有页面。现在,我尝试实现一个搜索功能。

问题#1 - 它只正确显示输入搜索结果的第一页,当我转到下一页时,它显示数据库中的其他项目(与搜索无关)。 [已解决]请参阅脚本中的更新。

问题#2 - 返回的页数是从整个数据库计算出来的(显示 +400 页),而不是例如只有 3 页,因为搜索结果应该是 45 项。

我的结构大纲是:

<?php
//FOR PAGINATION
$pages = new Paginator('15','n'); // number of items to show on each page

$stmt = $db->query("SELECT * FROM items "); //**FOCUS 1**
$pages->set_total($stmt->rowCount()); //pass number of records to PAGINATION

// SEARCH QUERY
if(isset($_GET['search_item'])){ // UPDATE-was POST
    $search_item = $_GET['search_item']; // UPDATE-was POST

    $stmt = $db->prepare("SELECT * FROM items WHERE item_name LIKE   '%".$search_item."%' OR item_code LIKE '%".$search_item."%' ORDER BY item_name ".$pages->get_limit());

$stmt->execute(array("%$search_item%"));
$set_total = ($stmt->rowCount());
//$min_length = 2; not necessary for example
}
?>

<!-- SEARCH FORM -->
<form method="GET" action=""><!-- **FOCUS 2** --> <!-- WAS PREVIOUSLY POST -->
    <input type="text" name="search_item" placeholder="search" style="width:200px;">
    <input type="submit" value="search" id="submit">
</form>

<!-- display results here in table format using while -->

<?php 
// PAGINATION RESULTS/PAGES DISPLAY
echo $pages->page_links('index.php?p=index&search_item='.$search_item.'&'); //**FOCUS 3** // UPDATE-was just  echo $pages->page_links();
?>

分页类:

class Paginator {

    private $_perPage;  // set the number of items per page. |@var numeric
    private $_instance; // set get parameter for fetching the page number | @var string
    private $_page; // sets the page number. | @var numeric
    private $_limit;    // set the limit for the data source | @var string
    private $_totalRows = 0;    // set the total number of records/items. | @var numeric

    // __construct | pass values when class is istantiated | @param numeric     $_perPage  sets the number of iteems per page | @param numeric  $_instance sets the instance for the GET parameter
    public function __construct($perPage,$instance){
        $this->_instance = $instance;
        $this->_perPage = $perPage;
        $this->set_instance();  
    }

    // get_start | creates the starting point for limiting the dataset | @return numeric
    private function get_start(){
        return ($this->_page * $this->_perPage) - $this->_perPage;
    }

    // set_instance | sets the instance parameter, if numeric value is 0 then set to 1 | @var numeric
    private function set_instance(){
        $this->_page = (int) (!isset($_GET[$this->_instance]) ? 1 : $_GET[$this->_instance]); // 1 was changed to 1
        $this->_page = ($this->_page == 0 ? 1 : $this->_page); // 1 was changed to 5
    }

    // set_total | collect a numberic value and assigns it to the totalRows | @var numeric
    public function set_total($_totalRows){
        $this->_totalRows = $_totalRows;
    }

    /**
    * get_limit
    * returns the limit for the data source, calling the get_start method and passing in the number of items perp page
    * @return string
    */
    public function get_limit(){
        return "LIMIT ".$this->get_start().",$this->_perPage";
    }

    /**
    * page_links
    * create the html links for navigating through the dataset
    * @var sting $path optionally set the path for the link
    * @var sting $ext optionally pass in extra parameters to the GET
    * @return string returns the html menu
    */
    public function page_links($path='?',$ext=null) {
        $adjacents = "2";
        $prev = $this->_page - 1;
        $next = $this->_page + 1;
        $lastpage = ceil($this->_totalRows/$this->_perPage);
        $lpm1 = $lastpage - 1;

        $pagination = "";
        if($lastpage > 1) {
        $pagination .= "<div class='pagination'>";
        if ($this->_page > 1)
        $pagination.= "<a href='".$path."$this->_instance=$prev"."$ext'>«</a>";
        else
        $pagination.= "<span class='disabled'>«</span>";   

        if ($lastpage < 7 + ($adjacents * 2)) { //7
            for ($counter = 1; $counter <= $lastpage; $counter++) {
                if ($counter == $this->_page)
                $pagination.= "<span class='current'>$counter</span>";
                else
                $pagination.= "<a href='".$path."$this->_instance=$counter"."$ext'>$counter</a>";                   
            }
        }
        elseif($lastpage > 3 + ($adjacents * 2)) { //3
            if($this->_page < 1 + ($adjacents * 2)) {
                for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++) { //4
                    if ($counter == $this->_page)
                    $pagination.= "<span class='current'>$counter</span>";
                    else
                    $pagination.= "<a href='".$path."$this->_instance=$counter"."$ext'>$counter</a>";                   
                }
                $pagination.= "...";
                $pagination.= "<a href='".$path."$this->_instance=$lpm1"."$ext'>$lpm1</a>";
                $pagination.= "<a href='".$path."$this->_instance=$lastpage"."$ext'>$lastpage</a>";       
            }
            elseif($lastpage - ($adjacents * 2) > $this->_page && $this->_page > ($adjacents * 2)) {

                $pagination.= "<a href='".$path."$this->_instance=1"."$ext'>1</a>";
                $pagination.= "<a href='".$path."$this->_instance=2"."$ext'>2</a>";
                $pagination.= "...";
                for ($counter = $this->_page - $adjacents; $counter <= $this->_page + $adjacents; $counter++) {
                    if ($counter == $this->_page)
                    $pagination.= "<span class='current'>$counter</span>";
                    else
                    $pagination.= "<a href='".$path."$this->_instance=$counter"."$ext'>$counter</a>";                   
                }

                $pagination.= "..";
                $pagination.= "<a href='".$path."$this->_instance=$lpm1"."$ext'>$lpm1</a>";
                $pagination.= "<a href='".$path."$this->_instance=$lastpage"."$ext'>$lastpage</a>";       
            } else {

                $pagination.= "<a href='".$path."$this->_instance=1"."$ext'>1</a>";
                $pagination.= "<a href='".$path."$this->_instance=2"."$ext'>2</a>";
                $pagination.= "..";
                for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++) {
                    if ($counter == $this->_page)
                    $pagination.= "<span class='current'>$counter</span>";
                    else
                    $pagination.= "<a href='".$path."$this->_instance=$counter"."$ext'>$counter</a>";                   
                }
            }
        }

        if ($this->_page < $counter - 1)
        $pagination.= "<a href='".$path."$this->_instance=$next"."$ext'>»</a>";
        else
        $pagination.= "<span class='disabled'>»</span>";
        $pagination.= "</div>\n";       
    }


    return $pagination;
}
}

尝试解决:

我一直在乱写代码,不记得我尝试过的所有内容,但我看到的是 FOCUS 区域。

FOCUS 1 我认为为了只为搜索输出的总结果生成分页,我需要添加类似 ("WHERE item_name LIKE '%".$search_item."%'" ),当我像 ("WHERE item_name LIKE 'ford') 这样编码时,它会显示正确的页数,但是当我循环浏览结果不正确时。只需添加 '%".$search_item."%' 到查询生成一个未定义的变量错误,我理解为 '%".$search_item."%' 直到编码后期才设置。

Focus 2 我已尝试将 method 更改为 GET 并将 action 更改为 action="index.php?p=index&amp;search=&lt;?php echo $search_item ;?&gt;". now this changes the URL to what i think should be correct 'index.php?search_item=ford' 但它仍然无法作为搜索功能的一部分因为我必须对 WHERE 进行硬编码才能显示结果(FOCUS 1)。

Focus 3 我不记得我做了什么,类似于 Focus 2 中的操作,但是当我将鼠标悬停在单独的页面上时,它显示了正确的 URL 路径我会期待的。

似乎当我尝试一件事时,它适用于其中一个焦点,但不适用于其他地方。

最近的 IV 到此为止!我现在可以正确显示项目,并且能够正确地循环浏览页面!我已将上面的代码修改为我现在所拥有的,以及我在 cmets 中“拥有”的内容。我现在遇到的问题是在分页中显示正确的页数 - 它显示了所有 +400 页,但是我的搜索变量传递到每一页,我可以循环浏览搜索结果,并且......它在应该的地方“切断”例如如果我只有 50 个结果,那么它将显示第 1、2、3 页的结果,然后在第 4+ 页上什么也不显示。

任何人都可以告诉我我哪里出错了或任何关于我应该看什么的建议。

【问题讨论】:

  • 问题#1 当你点击“第2页”时它不会知道$_POST['search_item']的值(因为它是一个新请求)。将该值存储在会话变量中。问题 #2 在第 5 行中,您使用 set_total 和未过滤的行数,这就是您得到的(在第 15 行中,您什么都不做,只是设置一个没有效果的变量。您可能是那里缺少$pages-&gt;)。
  • @Solarflare 我曾尝试创建一个会话,但现在一切都变得令人困惑,$_SESSION['search'] = $_POST['search_item'] 是我所做的并将其放在 FOCUS 1 上方的行中,然后将其添加到 SQL - "WHERE item_name LIKE $_SESSION['search']"我还需要通过第 5 行传递会话吗? - 抱歉,我整天都在这里,没有任何意义了。
  • a) 您必须先启动会话才能使用它。有关示例,请参见documentation b) 重点是:当您按下“第 2 页”时,$_POST['search_item'] 将为空。用现在为空的字符串替换会话变量没有帮助。当您输入搜索词时设置会话变量(例如,帖子变量不为空,并且帖子来自您的“搜索”表单),并在不是时使用会话变量(因此按下“第 n 页”)。或者编写自己的分页代码,并将搜索词作为参数添加到“第 n 页”
  • 到您的最后一个打开点:您仍然在第 5 行和第 6 行中设置总行数(以及总页数),而不使用搜索参数。您需要使用搜索参数执行此操作,以了解使用搜索参数有多少行(以及此页面),因此请执行完整查询并获取行数(您可能希望使用 select count(*) 来加快速度) if 带搜索参数,else 不带搜索参数并设置变量$pages-&gt;set_total 与该结果。

标签: php mysql pagination


【解决方案1】:

焦点 1

您的$pages-&gt;get_limit() 函数是否也返回SQL 查询的LIMIT 部分?在我的回复中,我假设该方法只返回一个整数。如果是这种情况,您的 SQL 查询中缺少 LIMIT

另外,我在您的示例代码中看不到您获取当前页码以帮助分页的任何地方。您的 Paginator 课程是否提供此功能?在下面的示例中,我分配了一个变量 $page,我假设当前页码在 $_GET['page'] 中。

试试这个:

$search_item = isset($_GET['search']) ? urldecode($_GET['search']) : null;

$page = 1;
if (isset($_GET['page']) && is_numeric($_GET['page']) && (int)$_GET['page'] > 0)
    $page = (int)$_GET['page'];

if (is_string($search_item) && mb_strlen($search_item) > 0) {
    $stmt = $db->prepare("SELECT * FROM items WHERE item_name LIKE :search_item 
      OR item_code LIKE :search_item ORDER BY item_name ASC LIMIT :limit OFFSET :offset");
} else {
    $stmt = $db->prepare("SELECT * FROM items ORDER BY item_name ASC LIMIT :limit OFFSET :offset");
}

if ($stmt->execute(
  array(
    'search_item' => '%' . $search_item . '%',
    'offset' => ($pages->get_limit() * ($page - 1)),
    'limit' => $pages->get_limit()
  )
)) {
    $set_total = $stmt->rowCount();
    $results = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

焦点 2

也许考虑将您的form 方法更改为GET 并使用$_GET 收集搜索过滤器,例如关键字和页码(如上例所示)。这将使您不必创建会话,并允许您轻松构建分页链接。

例子:

<?php $numPages = ceil($total / $pages->get_limit()); ?>
<ul class="pagination">
    <?php for ($p = 1; $p < ($numPages + 1); $p++) { ?>
        <li>
            <a href="index.php?p=search&search=<?php echo urlencode($search_item); ?>&page=<?php echo $p; ?>">
                <?php echo $p; ?>
            </a>
        </li>
    <?php } ?>
</ul>

或类似的东西:-)

【讨论】:

  • 我已经包含了上面的分页类,明天我会再看一遍。将form 方法更改为GET 是我尝试过的方法,它似乎纠正了一个问题,但随后其他领域出现问题,有时没有显示分页链接。
猜你喜欢
  • 1970-01-01
  • 2014-06-23
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 2016-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多