我确定这不是最好的方法,但我正在从下面的代码构建一个mysql查询。提供此代码的页面是带有复选框的表单。
根据所选的复选框,我可能会收到以下错误:
查询失败:您的SQL语法出错;检查手册 对应于您的MySQL服务器版本,以获得正确的语法 在')附近使用AND(downloads =“download1”OR downloads =“download2” 或者在第6行下载='
基于选择某些复选框,我正在尝试使用str_replace的回显查询变量:
SELECT url FROM crawler WHERE(genre =“Action”OR genre = “冒险”或类型=“街机”OR)AND(downloads =“download1”OR downloads =“download2”OR downloads =“download3”OR)
基本上,我需要在括号前摆脱最后的“OR”。代码底部的str_replace不起作用。它似乎没有找到“OR”。如果我将回显的查询变量剪切并粘贴到一个新变量中,str_replace工作正常,所以我看不到构造的查询字符串的问题。
<?php
include "connect.php";
$Action= $_GET["Action"];
$Adventure=$_GET["Adventure"];
$Arcade=$_GET["Arcade"];
$download1=$_GET["download1"];
$download2=$_GET["download2"];
$download3=$_GET["download3"];
if($Action=="true") {
$Action='genre = "Action" OR ';
}
else {
$Action="";
}
if($Adventure=="true") {
$Adventure='genre = "Adventure" OR ';
}
else {
$Adventure="";
}
if($Arcade=="true") {
$Arcade='genre = "Arcade" OR ';
}
else {
$Arcade="";
}
if($download1=="true") {
$download1='downloads = "download1" OR ';
}
else {
$download1="";
}
if($download2=="true") {
$download2='downloads = "download2" OR ';
}
else {
$download2="";
}
if($download3=="true") {
$download3='downloads = "download3" OR ';
}
else {
$download3="";
}
$query = "SELECT url FROM crawler WHERE
(
$Action
$Adventure
$Arcade
)
AND
(
$download1
$download2
$download3
)";
$query = str_replace('OR )', ')', $query);
echo $query."<br>";
$result = mysql_query($query) or die('Query failed: ' . mysql_error());
$number = mysql_num_rows($result);
echo "Result: ".number_format($number);
echo "<br><br>";
?>
答案 0 :(得分:1)
错误消息不会显示换行符,但这并不意味着没有换行符。 在您自己的定义中,您写道:
" ...
$download1
$download2
$download3
)";
因此在OR之前至少有一个换行符。
试试$query = str_replace("OR \n)", ")", $query);
。您可能需要更多或更少的空间。在更换之前仔细检查查询变量,以查看您需要更换的内容。
更简单的解决方案是让PHP为您提供连接元素,甚至可以自动化它。以下片段显示了一种灵活数量的类型的可能性,您可以在数组中轻松定义。
// Supported genres. You can get this from a database. You can also use
// it to generate a dynamic form with.
$genres = array('Action', 'Adventure', 'Arcade');
// Get the selected genres.
$genreConditions = array();
foreach ($genres as $genre)
{
if (array_key_exists($genre, $_GET) && $_GET[$genre] === 'true')
{
$genreConditions[] = "genre='$genre'";
}
}
// Build a clause from it.
$genreClause = "";
if (count($genreConditions) > 0)
{
$genreClause = '(' . implode($genreconditions, ' OR ') . ')';
}
// Do the same for downloads.
$downloadClause = "(downloads = 'download3')"; // stub
$allClauses = implode(array($genreClause, $downloadClause /*, ... others? */, ' AND ');
// Build the query
$query = 'SELECT url FROM crawler';
if ($allClauses !== '')
{
$query .= ' WHERE ' . $allClauses;
}
更好:这样做,但不是连接字符串值,而是连接?
并绑定参数。 :)
答案 1 :(得分:1)
就像您只使用OR一样,您可以使用Array来构建查询结构,然后使用implode()来代替str_replace。
这样的事情:
$sql = array();
if($Adventure == "true")
$sql[] = "genre = 'Adventure'";
if($Arcade == "true")
$sql[] = "genre = 'Arcade'";
$sql = implode(" OR ", $sql);
现在您可以将$ sql变量的内容放在查询中。
答案 2 :(得分:1)
您需要的是数组,内爆函数和SQL IN
运算符。另请注意,如果您删除OR
,则无论您的条件是否为真,您当前的查询都将失败。
$query = "SELECT ... FROM ...";
$genre = array();
$where = array();
if($Adventure == "true")
$genre[] = "'Adventure'";
if($Arcade == "true")
$genre[] = "'Arcade'";
...
if(count($genre)>0){
$where[] = "genre IN (" + implode(",", $genre) +")";
}
...
if(count($where)>0){
$sql += "WHERE " + implode(" AND ",$where);
}
答案 3 :(得分:1)
您不应该以您正在进行的方式进行编码。想象一下,如果你最终有100种类型,你的PHP将是巨大的。
相反,请考虑这些获取参数:
genres=Action,Adventure&downloads=1,2
由此,您可以创建一个简单的数组:
$genres = explode(',', $_GET['genres']);
使用数组,使用foreach
进行循环非常简单,但您也可以进行简单的内爆:
$query .= implode(' OR ', $genres);
请记住要转义变量,或者创建一个类型的白名单以避免SQL注入。
答案 4 :(得分:1)
此代码需要重构:
您可以在html表单中使用数组
<input type="checkbox" name="genres[]" value="action" />
<input type="checkbox" name="genres[]" value="adventure" />
然后在PHP方面:
$genres = $_POST['genres'];
array_walk($genres, function(&$v, $k){
$v = '"' . $v . '"';
});
$genres = implode(',', $genres);
在SQL查询中:
'...WHERE genre IN (' . $genres . ')...'
与下载相同..
请尝试使用PDO而不是mysql_函数 并且在进行查询之前不要忘记清理输入