PHP MySQL 变量过滤器 - "AND"行为类似于 "OR"

标签 php mysql variables filter

有没有更简单的方法使用url变量来过滤mysql结果?我编写了以下代码,它在一定程度上有效,我知道必须有一个更简单的方法,但我不知道从哪里开始。我宁愿更换这个,因为它只起作用了一半。

$start=0;
$limit=3;

if(isset($_GET['pg']))
{
$pg=$_GET['pg'];
$start=($pg-1)*$limit;
}
else { 
$pg = 1;
}
$sql = mysql_query($query);
if(isset($_GET['signage'])) {
    $result = mysqli_query($conn,"SELECT * FROM pilotOperators WHERE signage='1' LIMIT $start, $limit");
}
elseif(isset($_GET['certifications'])) {
    $certification = $_GET['certifications'];
    $result = mysqli_query($conn,"SELECT * FROM pilotOperators WHERE certifications='$certification' LIMIT $start, $limit");
}
elseif(isset($_GET['state'])) {
    $state = $_GET['state'];
    $result = mysqli_query($conn,"SELECT * FROM pilotOperators WHERE state='$state' LIMIT $start, $limit");
}
elseif(isset($_GET['certifications'], $_GET['signage'])) {
    $certification = $_GET['certifications'];
    $signage = $_GET['signage'];
    $result = mysqli_query($conn,"SELECT * FROM pilotOperators WHERE signage='$signage' AND certifications='$certification' LIMIT $start, $limit");
}
elseif(isset($_GET['certifications'], $_GET['signage'], $_GET['state'])) {
    $certification = $_GET['certifications'];
    $signage = $_GET['signage'];
    $state = $_GET['state'];
    $result = mysqli_query($conn,"SELECT * FROM pilotOperators WHERE signage='$signage' AND certifications='$certification' AND state='$state' LIMIT $start, $limit");
}
else {
    $result = mysqli_query($conn,"SELECT * FROM pilotOperators LIMIT $start, $limit");
}
while($row = mysqli_fetch_array($result))
{
echo "\n <table border='0' class='resultTable' width='75%'> \n";
echo "<tr> \n";
echo "<td width='120px'>ID: </td> \n";
echo "<td>" . $row['id'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>Name: </td> \n";
echo "<td>" . $row['name'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>Phone: </td> \n";
echo "<td>" . $row['phone'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>Alt. Phone: </td> \n";
echo "<td>" . $row['alt_phone'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>Fax: </td> \n";
echo "<td>" . $row['fax'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>Email: </td> \n";
echo "<td>" . $row['email'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>Website: </td> \n";
echo "<td><a href='" . $row['website'] . "' target='_blank'>" .  $row['website'] . "</a></td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>City: </td> \n";
echo "<td>" . $row['city'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>State: </td> \n";
echo "<td>" . $row['state'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>Certifications: </td> \n";
echo "<td>" . $row['certifications'] . "</td> \n";
echo "</tr> \n";
echo "<tr> \n";
echo "<td>Top Sign: </td> \n";
echo "<td>";
if($row['signage'] = 1) {
 echo "Has Top Sign";
}
else {
 echo "Top Sign Not Listed";
}
echo "</td> \n";
echo "</tr> \n";
echo "</table> \n\n";
}
$rows = mysqli_num_rows(mysqli_query($conn, "SELECT * FROM pilotOperators"));
$total=ceil($rows/$limit);
echo "<div id='paginationLinks'> \n";
if($pg>1)
{
echo "<a href='?pg=".($pg-1)."' class='paginationButton'>PREVIOUS</a> \n";
}
if($pg!=$total)
{
echo "<a href='?pg=".($pg+1)."' class='paginationButton'>NEXT</a> \n";
}

echo "<ul class='page'> \n";
 for($i=1;$i<=$total;$i++)
{
if($i==$pg) { echo "<li class='current'>".$i."</li> \n"; }

else { echo "<li><a href='?id=".$i."'>".$i."</a></li> \n"; }
}
echo "</ul> \n";
echo "</div> \n";
mysqli_close($con);

当我说这段代码有点工作时,请允许我解释一下。当我的网址中有多个变量(即?signage=VALUE&certifications=VALUE)时,代码的行为就像用 OR 代替 AND。

像这样:$result = mysqli_query($conn,"SELECT * FROM PilotOperators WHERE signage='$signage' OR Certifications='$certification' LIMIT $start, $limit");

而不是这样:$result = mysqli_query($conn,"SELECT * FROM PilotOperators WHERE signage='$signage' AND Certifications='$certification' LIMIT $start, $limit");

如果我的 URL 包含以下 &signage=1&certifications=washington,它不仅会向我显示同时具有这两者的结果,还会向我显示具有华盛顿认证或 Signage=1 的人员的结果。

我没有太多要传递的变量。应该只有3,但我的方法看起来很复杂。

我可以做些什么来使这个更简单,为什么我的AND在尝试过滤结果时表现得像OR。

最佳答案

问:我可以做些什么来简化这个过程?

答:您可以执行如下操作,有条件地将谓词附加到 SQL 语句,并推迟运行该语句,直到它完全构建。看起来您只需要运行一个 SQL 语句,因此只需要调用一次 mysqli_query。填充一个变量以包含 SQL 文本填充,并让 mysqli_query 引用该变量。

注意:任何潜在的不安全值必须正确转义以阻止 SQL 注入(inject)漏洞。 (请注意 SQL 文本中包含的每个值周围使用mysqli_real_escape_string函数。)

例如:

# start of SQL statement
$sql = "SELECT * FROM pilotOperators WHERE 1=1";

# append condition for signage (if required)
if(isset($_GET['signage'])) {
   $sql .= " AND signage='1'";
}

# append condition for certifications (if required)
if(isset($_GET['certifications'])) { 
   $certification = mysqli_real_escape_string($conn,$_GET['certifications']);
   $sql .= " AND certifications='$certification'"
}

# append condition for state (if required)
if(isset($_GET['state'])) {
   $state = mysqli_real_escape_string($conn,$_GET['state']);
   $sql .= " AND state='$state'";
}


# append ORDER BY and LIMIT 
$sql .= " ORDER BY 1,2,3";
$sql .= " LIMIT " . mysqli_real_escape_string($conn,$start) 
            . "," . mysqli_real_escape_string($conn,$limit);

#echo "SQL=" . $sql; // for debugging

$result = mysqli_query($conn,$sql);

我还添加了一个 ORDER BY 子句,因此行将以确定的顺序返回;将位置引用替换为所需的列。

WHERE 1=1 是一个虚拟占位符,其计算结果始终为 TRUE。这样做的目的是,任何后续谓词都可以使用 AND 添加,并且我们不需要费力去弄清楚这是否是第一个添加的谓词,我们需要使用 >WHERE 而不是 AND

所附加的每个部分的前导空格很重要。 (我只是发现将其作为主角处理更容易,而不是记住将其添加到末尾,但您可以在每个部分的末尾添加空格)。


问:为什么我的 AND 表现得像 OR?

答:事实并非如此,您永远不会遇到包含 AND 的语句。如果设置了“certifications”,则您执行的 SQL 语句仅包含 certifications 列上的谓词。您永远不会到达 elseif 来设置“certifications”和“state”。


跟进

上面的代码有一个错误,一行中缺少一个分号(语句终止符):

   $sql .= " AND certifications='$certification'" ;
                                                  ^

.= 运算符将右侧的值附加到左侧变量的当前值。也就是这个语句

$x .= "foo";

与此语句执行相同的操作。

$x = $x . "foo";

变量 $certification$state 并不是真正必要的。您可以删除这两行:

   $state = mysqli_real_escape_string($conn,$_GET['state']);
   $sql .= " AND state='$state'";

并将其替换为:

   $sql .= " AND state='" . mysqli_real_escape_string($conn,$_GET['state']) . "'";

但是将其分成两行确实可以更轻松地调试和发现错误,轻松添加 echovar_dump 进行调试...

   $state = mysqli_real_escape_string($conn,$_GET['state']);
   echo "state=" . $state ;
   var_dump($state);
   $sql .= " AND state='$state'";

关于PHP MySQL 变量过滤器 - "AND"行为类似于 "OR",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29972601/

相关文章:

php - MySQL 的 HTML 表单输入

php - 在 PHP 中显示带有序数后缀的日期

php - 查询包含多个字段的字段

MySql 根据第一个和最后一个关系之间的差异检索行

php - PHP echo 有长度限制吗?

linux - 在 Makefile 命令中设置变量

PHP、CURL、WebDAV 和 SEARCH 方法

php - mysql建表时使用变量作为表名

mysql - 如何创建 gpa 或 cgpa 触发器?

java - 未找到变量,即使它位于上面的类中