如何在同一页面上提交表单时预先填充下拉列表?

时间:2012-11-04 09:29:06

标签: php html forms session

我使用带有下拉列表的表单制作了一个过滤器。过滤器用于过滤mySQL数据库的结果。表单将在与结果相同的页面上处理。我想这样做,以便过滤器下拉列表在结果过滤后保留过滤器参数。

我过去通过使用会话来完成此操作,但是当我使用其他页面处理查询时。我试图应用同样的理论,但它没有用。我搜索过这个网站以及Google,我只找到了与单独页面相关的答案。

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

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

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;

我尝试将会话变量放在不同的位置,但这不起作用。我想也许刷新页面会工作,但后来我认为它会有效地删除过滤器,就像我提交表单两次时一样。有趣的是要注意的是,它是非常一致的,因为它每次提交时都会按字面意思运行,因此每个奇数提交它都不会填充,每个甚至提交它填充。

5 个答案:

答案 0 :(得分: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>

答案 1 :(得分:2)

这是您遇到的请求和会话问题。如果我正确地处理您的脚本,您会遇到以下情况:

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

在第二次提交时,然后在输出select标签后设置会话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变量也可以加上前缀,以便过滤器的名称可以使用请求变量进行命名空间,就像它已在会话中完成一样。

答案 2 :(得分: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,您将提取这些值并可能使用危险值覆盖您的变量。 这就是为什么我只复制$ REQUEST数组中的prefix值。

答案 3 :(得分: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']);
}

答案 4 :(得分:0)

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

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

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

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

<option <?php if(isset($prefix) && $prefix == "PDM"){echo "selected=\"selected\"";} ?> value="PDM">PDM</option>