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