实现 PHP 搜索过滤器表单的设计模式

Design pattern for implementing PHP search filter form

我正在用 PHP 编写的网站的搜索功能中实施过滤器。

我的目标是让这个易于管理,因为该项目的规模在接下来的时间里会增长很多。现在搜索页面有一些输入字段,php 通过检查表单按钮的名称是否在 $_POST 数组中来检查表单是否已提交。位于这个搜索页面的右侧,有一个实际搜索结果的列表,一个 foreach 循环的输出是打印到屏幕上的项目列表。为了更清楚地说明,我写了一些代码来解释它的作用,并展示了我自己想出的东西:

    <?php
    $arrayToDisplay = array(
            array("id"=>0,"name"=>"first","lastname"=>"last"),
            array("id"=>1,"name"=>"first","lastname"=>"last"),
    );

    $acceptedName = "";


    if(isset($_POST['buttonName'])) {
        if(isset($_POST['name'])) {
            $acceptedName = sanitize($_POST['name']);
        }
    }
?>

<form>
<input type="text" name="name">
<input type="submit" name="buttonName">
</form>

<?php


    foreach($arrayToDisplay as $person) {
            if(exists($acceptedName) && $acceptedName != "") {
                if($person["name" == $acceptedname) {
                    echo $person["id"]."  ".$person["name"];
                }       
            }
            else {
                echo $person["id"]."  ".$person["name"];
            }

    }
?>

这可以对一个值起作用,按名称过滤。但最终这些人对象将有近 50 个属性,搜索过滤器不仅要能够按名称过滤列表,还要过滤各种人的属性。这个解决方案是不可维护的。

是否存在可以在这种情况下使用的现有设计模式?

这个问题有很多方法,有些人认为您 can/should 键入每个表单元素及其相应的处理程序,因为如果您想使用文本框,维护起来会更容易,select 列表、单选按钮等。也就是说,您只是提到使用文本框,所以这里有一种方法可以使用单个数组来驱动整个应用程序。

  • 您没有提到您是否打算使用 SQL 来推动您的搜索,所以我假设您会使用它。
  • 您可以使用单个数组来驱动您的 HTML 表单和将由传入值生成的查询。

<?php

// This array will drive your form and your query.
$columns = [
    'firstname',
    'lastname',
    'email',
    'address_1',
    'address_2',
    'city'
];

// The form was submitted.
if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    // Match posted data to the `$columns` array and filter out any empty values.
    $postedData = array_filter(array_intersect_key($_POST, array_flip($columns)));

    // We have at least 1 search criteria to use.
    if (!empty($postedData)) {

        // Generate a list of columns for a WHERE clause. Ex. [`address_1 LIKE ?`, `name LIKE ?`]
        $terms = array_map(function ($val) {
            return "$val LIKE ? ";
        }, array_keys($postedData));

        // Generate a list of values wrapped in percent signs. Ex. [`123 King St.`, `%tony%`]
        $values = array_map(function ($val) {
            return "%$val%";
        }, $postedData);

        // Change this to `AND ` if needed.
        $query = 'SELECT * FROM table WHERE ' . implode('OR ', $terms);

        // Just showing you what the generated query and data looks like.
        var_dump([
            $query,
            array_values($values)
        ]);

        // Finally, use them to drive your query.
        // $sql = $connection->prepare($query);
        // $sql->execute(array_values($values));
    }
}

?>

<form method="post">
    <?php foreach ($columns as $column): ?>
        <label>
            <input type="text" name="<?php echo $column; ?>" placeholder="<?php echo $column; ?>">
        </label>

        <br>
    <?php endforeach; ?>

    <input type="submit" value="Search">
</form>

示例输出

array (size=2)
  0 => string 'SELECT * FROM table WHERE firstname LIKE ? OR email LIKE ? ' (length=59)
  1 => 
    array (size=2)
      0 => string '%Tony%' (length=6)
      1 => string '%tony@email.com%' (length=16)