2

我使用带有下拉列表的表单制作了一个过滤器。过滤器用于过滤来自 mySQL 数据库的结果。表单与结果在同一页面上处理。我想让过滤器下拉列表在过滤结果后保留过滤器参数。

我过去通过使用会话来完成此操作,但是那是我使用另一个页面来处理查询的时候。我试图应用同样的理论,但它不起作用。我已经搜索了这个网站以及谷歌,我只找到了与一个单独的页面相关的答案以进行处理。

目前,我拥有的代码只会在提交两次后才预填充表单。第一次提交时,它显示“选择...”的默认设置

以下是我的代码的相关部分:

session_start();
if(isset($_SESSION['submitted_filter_values']))
{
extract($_SESSION['submitted_filter_values']);
}

<form action="#filter" method="post" name="filter">
<table>

<tr>
<td>
<select name="prefix">
<option value="">Select...</option>
<option <?php if(isset($prefix) && $prefix == "PDM"){echo "selected=\"selected\"";} ?> value="PDM">PDM</option>
<option <?php if(isset($prefix) && $prefix == "TB"){echo "selected=\"selected\"";} ?> value="TB">TB</option>
<option <?php if(isset($prefix) && $prefix == "JNL"){echo "selected=\"selected\"";} ?> value="JNL">JNL</option>
</select>
</td>
</tr>

<tr align="center">
<td colspan="2"><input type="submit" class="btn_150x30" name="submit" value="Filter Results"></td>
</tr>

</table>
</form>

$_SESSION['submitted_filter_values'] = $_REQUEST;

我曾尝试将会话变量放在不同的位置,但没有奏效。我认为刷新页面可能会起作用,但后来我认为它会像我两次提交表单时一样有效地删除过滤器。需要注意的有趣的一点是,它非常一致,因为它在我每第二次提交时都会正常工作,所以每一次奇数提交它都不会填充,而每一个偶数提交它都会填充。

4

5 回答 5

3

试试这个:

<?php 
    session_start();

    if(isset($_POST['prefix'])){
        // if the form has been posted use it
        $prefix = $_POST['prefix']; // <------ RUN SOME VALIDATION HERE!!!!!!!
        $_SESSION['submitted_filter_values'] = $prefix; // update the session var

    }elseif(isset($_SESSION['submitted_filter_values'])){
        // if the form hasn't been posted then look in the $_SESSION
        $prefix = $_SESSION['submitted_filter_values']; // <------ RUN SOME VALIDATION HERE (trust no one!)!!!!!!!
    }



?>
    <form action="#filter" method="post" name="filter">
        <table>

            <tr>
                <td>
                    <select name="prefix">
                        <option value="">Select...</option>
                        <option<?php if($prefix == "PDM"){echo " selected=\"selected\"";} ?> value="PDM">PDM</option>
                        <option<?php if($prefix == "TB"){echo " selected=\"selected\"";} ?> value="TB">TB</option>
                        <option<?php if($prefix == "JNL"){echo " selected=\"selected\"";} ?> value="JNL">JNL</option>
                    </select>
                </td>
            </tr>
            <tr align="center">
                <td colspan="2">
                    <input type="submit" class="btn_150x30" name="submit" value="Filter Results" />
                </td>
            </tr>

        </table>
    </form>
于 2012-11-04T09:42:38.817 回答
2

这是您遇到的请求和会话问题。如果我按照你的脚本处理对了,你有以下情况:

首次提交时,submitted_filter_values未设置会话。您将看到默认条目,$prefix保持未设置。

在第二次提交时,您在输出选择标签submitted_filter_values 后设置会话。由于该顺序,您仍然会看到默认条目。

在第三次提交时,您将看到第二次提交的过滤器。

在第四次提交时,您将看到第三次提交的过滤器。等等等等。

如果您不提交而只是通过 GET 请求,则该值仍然存在,但是您还将会话设置submitted_filter_values回默认值,因为$_REQUEST不再包含prefix任何内容。

看到这个顺序也有助于改变脚本。一条经验法则是在脚本之上处理输入变量(设置与否)。在编写@Chris 时已经为此提供了代码——我会做的有点不同,但他的例子展示了它是如何工作的。

我首先会在顶部定义过滤器,使用请求和会话逻辑一个接一个地处理它们,然后输出表单。这样做的好处是您可以更改顶部的数据逻辑和输出中的输出逻辑。

<?php
session_start();

/**
 * define your filter(s)
 */
$filters = array(
    'prefix' => array(
        'value' => null,
        'list' => array('PDM', 'TB', 'JNL')
    )
);

$filtersSessionName = 'submitted_filter_values';

/**
 * process the state of your filter(s) with request input and
 * session state
 */
foreach($filters as $name => $filter) {

    // does request has filter value set?
    if (isset($_REQUEST[$name])) {
        $requestValue = $_REQUEST[$name];
        // does it validate?
        if (in_array($requestValue, $filter['list'])) {
            $filter['value'] = $requestValue;
            $_SESSION[$filtersSessionName][$name] = $requestValue;
            continue;
        }
    }

    // does the session has filter value set?
    if (isset($_SESSION[$filtersSessionName][$name])) {
        $sessionValue = $_SESSION[$filtersSessionName][$name];
        // does it validate?
        if (in_array($sessionValue, $filter[$list])) {
            $filter['value'] = $sessionValue;
            continue;
        }
    }
}


/**
 * output the filter(s) in the form
 */
?>

<form action="#filter" method="post" name="filter">
    <table>
        <?php foreach($filters as $name => $filter) { ?>
            <tr>
                <td>
                    <select name="<?php echo $name; ?>">
                        <option value="">Select ...</option>
                        <?php foreach($filter['values'] as $label) {
                            $selected = $filter['value'] === $label;
                        ?>
                            <option <?php if ($selected) { echo 'selected="selected"';} ?> value="<?php echo $label ?>">
                                <?php echo $label ?>
                            </option>
                        <?php } ?>
                    </select>
                </td>
            </tr>
        <?php } # foreach filters ?>
        <tr align="center">
            <td colspan="2"><input type="submit" class="btn_150x30" name="submit" value="Filter Results"></td>
        </tr>
    </table>
</form>

这可以通过对过滤器列表使用键/值对来进一步改进,以便过滤器的标签可以与正在提交的值不同。此外,$_REQUEST变量也可以加上前缀,以便过滤器的名称将与请求变量一起命名,就像它已经在会话中完成一样。

于 2012-11-04T09:43:37.007 回答
1

您需要改变处理$REQUEST结果的方式。

<?php
session_start();
if (isset($REQUEST))  // do we have a submitted request?
{         // yes -> save it in session

    $_SESSION['submitted_filter_values']['prefix'] = $REQUEST['prefix'];
    $prefix = $REQUEST['prefix'];

} else {  // no -> try to retrieve it from the session

   if(isset($_SESSION['submitted_filter_values']))
   {
      $prefix = extract($_SESSION['submitted_filter_values']['prefix']);
   }

}
?>

<form action="#filter" method="post" name="filter">
<table>

<tr>
<td>
<select name="prefix">
<option value="">Select...</option>
<option <?php if(isset($prefix) && $prefix == "PDM"){echo "selected=\"selected\"";} ?> value="PDM">PDM</option>
<option <?php if(isset($prefix) && $prefix == "TB"){echo "selected=\"selected\"";} ?> value="TB">TB</option>
<option <?php if(isset($prefix) && $prefix == "JNL"){echo "selected=\"selected\"";} ?> value="JNL">JNL</option>
</select>
</td>
</tr>

<tr align="center">
<td colspan="2"><input type="submit" class="btn_150x30" name="submit" value="Filter Results"></td>
</tr>

</table>
</form>

关于extract,将它与不受信任的输入(如 $REQUEST 数组)一起使用是非常糟糕的做法,它可能包含不需要的值。想象一下,有人伪造了一个以该页面为目标的 URL,其中一些参数覆盖了脚本中的某些值,因为您使用 $REQUEST,您将提取这些值并可能用危险值覆盖您的变量。这就是为什么我只复制prefix$REQUEST 数组中的值。

于 2012-11-04T09:46:55.397 回答
0

我认为,根据您当前的代码段,您需要设置代码序列如下

if(isset($_REQUEST))
{
   $_SESSION['submitted_filter_values'] = $_REQUEST;
}

if(isset($_SESSION['submitted_filter_values']))
{
   extract($_SESSION['submitted_filter_values']);
   unset($_SESSION['submitted_filter_values']);
}
于 2012-11-04T09:43:52.120 回答
0

在意识到会话对我的应用程序来说不是一个好主意后,因为它只在一个页面上使用,而不是在整个站点上使用,我采取了一种新的方法来解决这个问题。

在我的过滤器顶部,每个选项都有这个:

if(isset($_POST['prefix']))
    {
    $prefix = $_POST['prefix'];
    }

然后在我的下拉列表中,每个选项都有这个:

<option <?php if(isset($prefix) && $prefix == "PDM"){echo "selected=\"selected\"";} ?> value="PDM">PDM</option>
于 2012-11-05T04:39:50.057 回答