str_replace无法按预期工作

时间:2014-07-01 22:02:39

标签: php mysql str-replace

我确定这不是最好的方法,但我正在从下面的代码构建一个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>";

?>

5 个答案:

答案 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_函数 并且在进行查询之前不要忘记清理输入