【问题标题】:Filter Search Results from a Dropdown in PHP从 PHP 中的下拉列表中过滤搜索结果
【发布时间】:2019-12-17 22:18:17
【问题描述】:

我已经建立了一个搜索 (https://brawlins.com/oer/index.php),我希望用户能够选择过滤器来限制初始搜索后的搜索结果。我在我的搜索页面 (https://brawlins.com/oer/search.php?term=) 的下拉菜单中填充了过滤器,但我不确定一旦用户点击它们后如何过滤结果。我希望用户也能够选择多个选项。我创建了一个类来存储过滤器。下面是我的过滤器类的代码:

    <?php
class filterContentProvider {

    private $conn;

    public function __construct($conn) {
        $this->conn = $conn;
    }

    public function getType ($conn) {

        $query = $this->conn->prepare("SELECT type, COUNT(*) as total FROM oer_search GROUP BY type");
        $query->execute();

        $filterHTML .= "<h3 class='filterTitle'>Type</h3>";  
        $filterHTML .= "<div class'dropdown'>";
        $filterHTML .= "<button class='btn btn-filter dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>Select - Type</button>";
        $filterHTML .= "<div class='dropdown-menu scrollable-menu' aria-labelledby='dropdownMenuButton'>";

        //$filterHTML .= "<option value=''>- Type -</option>"; 

        while($row = $query->fetch(PDO::FETCH_ASSOC)) {
            $type = $row["type"];
            $total = number_format($row["total"]);
            $filterHTML .= "<a class='dropdown-item' href='search.php?type=$type'>$type ($total)</a>";
        }

        $filterHTML .= "</div>";
        $filterHTML .= "</div>"; //end of dropdown

        return $filterHTML;
    }

    public function getSubject ($conn) {

        $query = $this->conn->prepare("SELECT subject, COUNT(*) as total  FROM oer_search GROUP BY subject");
        $query->execute();

        $filterHTML .= "<h3 class='filterTitle'>Subject</h3>";  
        $filterHTML .= "<div class'dropdown'>";
        $filterHTML .= "<button class='btn btn-filter dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>Select - Subject</button>";
        $filterHTML .= "<div class='dropdown-menu scrollable-menu' aria-labelledby='dropdownMenuButton'>";

        while($row = $query->fetch(PDO::FETCH_ASSOC)) {
            $subject = $row["subject"];
            $total = number_format($row["total"]);
            if ($subject != "") {
              $filterHTML .= "<a class='dropdown-item' href='search.php?subject=$subject'>$subject ($total)</a>";  
            }
        }

        $filterHTML .= "</div>";
        $filterHTML .= "</div>"; //end of dropdown

        return $filterHTML;
    }


    public function getLicense ($conn) {

        $query = $this->conn->prepare("SELECT license, COUNT(*) as total FROM oer_search GROUP BY license");
        $query->execute();

        $filterHTML .= "<h3 class='filterTitle'>License</h3>";  
        $filterHTML .= "<div class'dropdown'>";
        $filterHTML .= "<button class='btn btn-filter dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>Select - License</button>";
        $filterHTML .= "<div class='dropdown-menu scrollable-menu' aria-labelledby='dropdownMenuButton'>"; 

        while($row = $query->fetch(PDO::FETCH_ASSOC)) {
            $license = $row["license"];
            $total = number_format($row["total"]);
            if ($license != "") {
              $filterHTML .= "<a class='dropdown-item' href='index-test.php?license=$license'>$license ($total)</a>";  
            }
        }

        $filterHTML .= "</div>";
        $filterHTML .= "</div>"; //end of dropdown

        return $filterHTML;
    }

    public function getReviewed ($conn) {

        $query = $this->conn->prepare("SELECT review, COUNT(*) as total FROM oer_search GROUP BY review");
        $query->execute();

        $filterHTML .= "<h3 class='filterTitle'>Reviewed</h3>";  
        $filterHTML .= "<div class'dropdown'>";
        $filterHTML .= "<button class='btn btn-filter dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>Select - Reviewed</button>";
        $filterHTML .= "<div class='dropdown-menu scrollable-menu' aria-labelledby='dropdownMenuButton'>"; 

        while($row = $query->fetch(PDO::FETCH_ASSOC)) {
            $review = $row["review"];
            $total = number_format($row["total"]);
            if ($review != "") {
              $filterHTML .= "<a class='dropdown-item' href='index-test.php?review=$review'>$review ($total)</a>";  
            }
        }

        $filterHTML .= "</div>";
        $filterHTML .= "</div>"; //end of dropdown

        return $filterHTML;
    }

    public function getOrigin ($conn) {

        $query = $this->conn->prepare("SELECT source, COUNT(*) as total FROM oer_search GROUP BY source");
        $query->execute();

        $filterHTML .= "<h3 class='filterTitle'>Source</h3>";  
        $filterHTML .= "<div class'dropdown'>";
        $filterHTML .= "<button class='btn btn-filter dropdown-toggle' type='button' id='dropdownMenuButton' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>Select - Source</button>";
        $filterHTML .= "<div class='dropdown-menu scrollable-menu' aria-labelledby='dropdownMenuButton'>"; 

        while($row = $query->fetch(PDO::FETCH_ASSOC)) {
            $source = $row["source"];
            $total = number_format($row["total"]);
            if ($source != "") {
              $filterHTML .= "<a class='dropdown-item' href='index-test.php?source=$source'>$source ($total)</a>";  
            }
        }

        $filterHTML .= "</div>";
        $filterHTML .= "</div>"; //end of dropdown

        return $filterHTML;
    }

}

?>

这是我在 search.php 页面上使用的代码。任何帮助将不胜感激。

<?php   
include("config.php");
include("classes/siteResultsProvider.php");
include("classes/imageResultsProvider.php");
include("classes/filterContentProvider.php");
include("classes/filterImageProvider.php");

    if(isset($_GET["term"])){
        $term = $_GET["term"];
    }

    if(isset($_GET["collection"])){
        $collection = $_GET["collection"];
    }
    else {
        $collection = "open_content";
    }

    $page = isset($_GET["page"]) ? $_GET["page"] : 1;

?>

<!DOCTYPE html>
<html lang="en">
<head>
    <title>SOAR</title>
<?php
include("header.php");
?>

    <div class="wrapper">
        <div class="header">
            <div class="headerContent">
                <div class="searchContainer">
                    <form action="search.php" method="GET">
                        <div class="searchBarContainer">
                            <input type="hidden" name="collection" value="<?php echo $collection; ?>">
                            <input class="searchBox" type="text" name="term" value="<?php echo htmlspecialchars($term, ENT_QUOTES) ?>" aria-label="search box">
                            <button class="searchButton">
                                <img src="images/search-icon.png" alt="search icon">
                            </button>
                        </div>
                    </form>
                </div>

            </div><!--end of headerContent-->

            <div class="tabsContainer">
                <ul class="tabList">
                    <li class="<?php echo $collection == 'open_content' ? 'active' : '' ?>">
                        <a href='<?php echo "search.php?term=$term&collection=open_content"; ?>'><i class="fas fa-book-open"></i> Open Content</a>
                    </li>
                    <li class="<?php echo $collection == 'images' ? 'active' : '' ?>">
                        <a href='<?php echo "search.php?term=$term&collection=images"; ?>'><i class="fas fa-images"></i> Images</a>
                    </li>
                </ul>
            </div>
        </div><!--end of header-->

<!-------------------------beginning of main section where seach results will display-------------------------->
        <?php
                if($collection == "open_content") {
                    $filters = new filterContentProvider($conn);
                }
                else {
                    $filters = new filterImageProvider($conn);
                }

           if($collection == "open_content") {

                $filterType = $filters->getType($conn);
                $filterSubject = $filters->getSubject($conn);
                $filterOrigin = $filters->getOrigin($conn);
                $fitlerLicense = $filters->getLicense($conn);
                $filterReviewed = $filters->getReviewed($conn);

                echo "<div class='filterContainer'>
                        <div class='filterContent'>
                            <div class='filter'>
                                $filterType
                            </div>
                            <div class='filter'>
                                $filterSubject
                            </div>
                            <div class='filter'>
                                $filterOrigin
                            </div>
                            <div class='filter'>
                                $fitlerLicense
                            </div>
                            <div class='filter'>
                                $filterReviewed
                            </div>
                        </div>
                     </div>"; 
            }
            else {

                $imageFilterOrigin = $filters->getImageOrigin($conn);
                $imageFilterLicense = $filters->getImageLicense($conn);

                echo "<div class='filterContainer'>
                            <div class='filterContent'>
                                <div class='filter'>
                                    $imageFilterOrigin
                                </div>
                                <div class='filter'>
                                    $imageFilterLicense
                                </div>
                            </div>
                         </div>"; 

            }

        ?>

        <div class="mainResultsSection">

            <?php

                if($collection == "open_content") {
                    $resultsProvider = new siteResultsProvider($conn);
                    $pageSize = 25;
                }
                else {
                    $resultsProvider = new imageResultsProvider($conn);
                    $pageSize = 50;
                }  

                $numResults = $resultsProvider->getNumResults($term);

                echo "<p class='resultsCount'>" . number_format($numResults) . " results found</p>";

                echo $resultsProvider->getResultsHTML($page, $pageSize, $term);
            ?>

        </div>

        <div class="paginationContainer">
            <div class="pageButtons">
                <div class="pageNumberContainer">
                    <img src="images/pageStart.png" alt="Start of page image">
                </div>

                <?php
                    $pagesToShow = 10;
                    $numPages = ceil($numResults / $pageSize);
                    $pagesLeft = min($pagesToShow, $numPages);

                    $currentPage = $page - floor($pagesToShow / 2);

                    if($currentPage < 1) {
                        $currentPage = 1;
                    }

                    if($currentPage + $pagesLeft > $numPages + 1) {
                        $currentPage = $numPages + 1  - $pagesLeft;
                    }

                    while($pagesLeft != 0 && $currentPage <= $numPages) {

                        if($currentPage == $page) {
                            echo "<div class='pageNumberContainer'>
                                <img src='images/pageSelected.png' alt='selected page page image'/>
                                <span class='pageNumber'>$currentPage</span>
                                </div>";
                        }
                        else {
                            echo "<div class='pageNumberContainer'>
                                    <a href='search.php?term=$term&collection=$collection&page=$currentPage'>
                                        <img src='images/page.png' alt='pages image'/>
                                        <span class='pageNumber'>$currentPage</span>
                                    </a>
                                </div>";
                        }

                        $currentPage++;
                        $pagesLeft--;

                    }
                ?>

                <div class="pageNumberContainer">
                    <img src="images/pageEnd.png" alt="End of page image">
                </div>
            </div>

        </div><!--end of pagination container-->
    </div><!--end of wrapper-->

    <script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>
    <script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
    <script type="text/javascript" src="js/script.js"></script>
</body>
</html>

【问题讨论】:

  • 您可以添加另一个表单,该表单回发到您保存在主表单之前运行的过滤器选择的同一页面。一旦这些在查询字符串中,您就可以将它们用作 $_GET 变量来检查要过滤的内容。
  • 通过一点参数化,您可以创建一个被调用 5 次的 get... 子例程。
  • 嗨瑞克,这就是我遇到麻烦的地方。我不知道该怎么做。
  • @brawlins4 在我的回答中查看 test.php 文件
  • 如果您喜欢使用 Ajax,您可以使用我可以帮助您吗?

标签: php mysql


【解决方案1】:

您似乎需要做几件事才能使其正常工作。

如果您希望结果是异步的:

  1. 为您选择的输入添加一个 onchange 事件。 (类似于onchange="addFilter('type', this.value)")见https://www.w3schools.com/jsref/event_onchange.asp
  2. 让 onchange 函数 (addFilter) 通过 AJAX 请求将过滤器和查询字符串发送回您的 PHP 脚本。如果你使用 jQuery,get 方法会为你工作。 https://api.jquery.com/jquery.get/
  3. 使用您传递的 $_GET 参数在 PHP 中提取新结果。 (就像您已经在脚本中所做的那样。)您只想回显结果,而不是页面的导航和其他元素。
  4. 使用(类似于 jQuery 中的 $('#myContainer').html(results);)更新页面上的搜索结果
  5. 另外,最好更新地址栏中的 URL 参数How do I modify the URL without reloading the page?

这是一个非常简单的例子:

test.php

<?php

// Look up the results here
// You'll probably want to do something more performant that this; it's just a lazy example. :)
// ...
$query = $this->conn->prepare("SELECT type, COUNT(*) as total FROM oer_search WHERE type LIKE :type AND subject LIKE :subject GROUP BY type");
$query->execute([
  'type' => isset($_GET['type'] ? $_GET['type'] : '%',
  'subject' => isset($_GET['subject'] ? $_GET['subject'] : '%',
]);
// ...
?>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="jquery-3.4.1.min.js"></script>
  <script>
    function addFilter(name, value) {
      var url = '/test.php?';
      var urlParams = new URLSearchParams(window.location.search);
      var keys = urlParams.keys();
      for(key of keys) { 
        if (key == name) {
          continue;
        }
        url += key + '=' + urlParams.get(key) + '&';
      }

      url += name + '=' + value;
      window.history.pushState({}, "", );
      $.get(url, function(data) {
        $('#results').html(data);
      });
    }
  </script>
</head>
<body>
  <select onchange="addFilter('type', this.value)">
    <option></option>
    <option>value 1</option>
    <option>value 2</option>
  </select>
  <select onchange="addFilter('subject', this.value)">
    <option></option>
    <option>value 1</option>
    <option>value 2</option>
  </select>
  <div id="results"></div>
</body>
</html>

如果您不关心/希望重新加载页面:

只需让onchange 事件再次提交带有搜索参数的表单。如果您使用 jQuery,submit 方法将起作用。请务必在选择输入中适当地选择选项,否则它们每次都会清除(无法设置多个)。

【讨论】:

  • 你的解决方案是完美的,我赞成
猜你喜欢
  • 2023-03-26
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
  • 2014-09-16
  • 1970-01-01
  • 1970-01-01
  • 2011-06-17
相关资源
最近更新 更多