我正在用PHP构建一个搜索页面,使用多个选择选项,并通过GET方法将值从一个页面传递到另一个页面。
但是我被WHERE子句卡住了,在那里未传递的值不会填充我的查询,最终我总是会收到没有找到记录。我尝试了一些方法,详细介绍了一些相关的帖子,如:建议使用SQL WHERE column = everything和Why would someone use WHERE 1=1 AND in a SQL clause?,其中WHERE column=column(1=1),但正如第一个链接中所述,这不是一个有效的解决方案。
一个建议的工作解决方案是使用IF情况,但如果我考虑我的15个选项和它的所有类型的组合,(当一些被选中,一些被取消选中,'NULL'/any/all值,我立即感到头痛。
因此,我考虑询问是否可以基于传递的参数构建这个WHERE条件并将其应用于查询。
编辑1.
@Flewz我的过滤器看起来像:
通过GET得到这样的结果
]
我的数据库如下所示:
我的where子句是
$stmt = $conn->prepare("SELECT * FROM Mydatabase WHERE mushtype='$mushtype'AND capsurface='$capsurface' AND capform='$capform')
我没有在这里重复所有15个过滤器,这在时间上可能会更多,但你的想法。
所以,用户不需要使用所有的过滤器来识别它的蘑菇,它只会使用需要的一个,但在我的句子中,如果一列没有使用,返回给我一个没有找到记录消息,我想避免这种情况。我愿意接受任何建议。
编辑2.
感谢@Flewz给我这么漂亮的指南,这让我很惊讶,我不需要任何编程技巧就能理解它,并根据我的需要进行调整。**(一切)。我在哪里能够看到发生在每一行的代码,并遵循它,直到最后。我在哪里需要改变一点这个指南在这里:
if($get_var_size == 0){
// no point in doing anything,
// echo error message
echo 'Please select at least one filtering condition'; // echo 'I am a teapot';
exit();
}
原因是,我不想返回一个错误消息,如果没有选择,因为这将意味着用户要列出所有可用的记录,这是没有必要的错误。第二节是与上述内容有关,在这里:
// in addition we can check if we have all get params and adjust query
if($get_var_size == count($all_get_keys)){
// execute
}
因为**if $get_var_size == count($all_get_keys)表示用户填写了所有可能的条件,所以我的查询$sql = 'SELECT * FROM some_table';**不是这个,而是从ELSE分支构建的一个完全定制的查询,所以,我把这个IF分支切掉了,认为它不需要。
到目前为止一切顺利,但我还没有完成,我仍然有一个问题。倒带和总结一下,我有一个索引页与此代码(使用3过滤器为一个较短的代码示例):
<form name="search_form" role="form" method="GET" id="search_form" action="SearchResults.php">
<?php
try {
$conn = new PDO('sqlite:db/Ciupercomania.db');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
?>
<select id="mushtype" name="mushtype" style="width: 30vw;">
<option value="" selected disabled hidden>Choose</option>
<?php
$stmt = $conn->prepare("SELECT * FROM attributes WHERE attributename='mushtype' ORDER by attributevalueEN ASC");
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($data as $row): ?>
<option value="<?php echo $row['idattributevalue']; ?>"><?php echo $row['attributevalueEN']; ?></option>
<?php endforeach; ?>
</select>
<select id="capform" name="capform" style="width: 30vw;">
<option value="" selected disabled hidden>Choose</option>
<?php
$stmt = $conn->prepare("SELECT * FROM attributes WHERE attributename='capform' ORDER by attributevalueEN ASC");
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($data as $row): ?>
<option value="<?php echo $row['idattributevalue']; ?>"><?php echo $row['attributevalueEN']; ?></option>
<?php endforeach; ?>
</select>
<select id="capsurface" name="capsurface" style="width: 30vw;">
<option value="" selected disabled hidden>Choose</option>
<?php
$stmt = $conn->prepare("SELECT * FROM attributes WHERE attributename='capsurface' ORDER by attributevalueEN ASC");
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($data as $row): ?>
<option value="<?php echo $row['idattributevalue']; ?>"><?php echo $row['attributevalueEN']; ?></option>
<?php endforeach; ?>
</select><br><br>
<?php
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
$conn = null;
?>
<input type="submit" value="Find Your Mushroom">
</form>
和一个“结果”页面,其中包含
<?php
// declaring all parameters I expect to pass through GET method
$all_get_keys = ['mushtype', 'capform', 'capsurface'];
// we will use this to make our sql statement
$get_key_config = [
'mushtype' => [
'db_col' => 'mushtype',
'assoc_var' => 'mushtype'
],
'capform' => [
'db_col' => 'capform',
'assoc_var' => 'capform'
],
'capsurface' => [
'db_col' => 'capsurface',
'assoc_var' => 'capsurface'
]
];
// for parsed $_GET
$get_params = [];
// go over all possible keys
foreach ($all_get_keys as $key) {
// if we have it, push to array
if (isset($_GET[$key])) {
$get_params[] = [
'key' => $key,
'value' => $_GET[$key]
];
}
}
// how many we got
$get_var_size = count($get_params);
try {
$conn = new PDO('sqlite:db/Ciupercomania.db');
$conn -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt_data = [];
$sql = 'SELECT IDmush, genus, species, img1 FROM mushroomdata ';
// adjusting the query
if ($get_var_size == 0) {
} else {
$sql .= ' WHERE ';
for ($i = 0; $i < $get_var_size; $i++) {
// get config for our get key
$cfg = $get_key_config[$get_params[$i]['key']];
// append to sql query
$sql .= $cfg['db_col'] . '=:' . $cfg['assoc_var'];
// don't forget on variable
$stmt_data[$cfg['assoc_var']] = $get_params[$i]['value'];
// don't add AND if its our last
if ($i < $get_var_size - 1) {
$sql .= ' AND ';
}
}
}
$stmt = $conn->prepare($sql);
$stmt -> execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo '<ul class="no-bullets">';
if ( !empty($data) ) {
foreach ( $data as $row ){
echo '<a target="blank" href="Datasheet.php?IDmush='.$row['IDmush'].'">' .
'<li>'.$row['genus'].' '.$row['species'].'</li>'.
'</a>';
}
} else {
echo "No records found.";
}
echo '</ul>';
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
// temporary messages
echo "<pre>";
echo "all-get-keys<br/>"; print_r($all_get_keys); echo '<br/>';
echo "stmt_data<br/>"; print_r($stmt_data); echo '<br/>';
echo "sql statement<br/>"; print_r($sql); echo '<br/>';
echo "</pre>";
$conn = null;
?>
运行此代码并应用一些过滤参数,我再次收到此意外消息未找到记录x1c4d 1x
由于Flewz的帮助,SQL查询被正确构建,并且可以在屏幕截图中看到,我确信是我在执行命令时的错误,但我不知道在哪里。未排序的列表部分也是正确的,我已经在其他页面上使用了它。请帮助我识别我在执行命令时的错误。谢谢。
2条答案
按热度按时间4xrmg8kj1#
既然你已经更新了你的问题,让我们从一些安全的做法开始。
您使用的是预准备语句,这很好,只是您的方法不对。
因为你使用的是php,我们有一个命名参数选项,见下面的例子。
WHERE species=:species
:species是我们在预准备语句中的变量,我们通过传递一个带键的数组给execute
方法来填充它,这是唯一安全的方法。对于你手头的问题,最容易理解的是大量的if语句。可以用配置对象和一个for循环来完成。
未经测试,可能行不通。
if和for循环之间的唯一区别是config中的选项将被类型化为if语句。
q8l4jmvw2#
WHERE子句是用来过滤数据的,所以如果你不需要过滤(想查看所有记录),完全跳过WHERE子句就行了,它是不需要的。