“&安培;”并且“准备好的陈述中的”和“失败”

时间:2013-10-03 16:38:09

标签: php sql pdo prepared-statement

我有一大堆PHP代码(简称为简洁)作为一个准备好的语句,允许用户使用系列标题搜索数据库...

$series = null;
if (isset($_GET["series"])) $series = $_GET["series"];

try {
    $dbh = new PDO("sqlsrv:Server=localhost;Database=Radio", "", "");
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    if (isset($series)) {
        $sql = "SELECT *
            FROM dbo.Schedule
            WHERE dbo.Schedule.Series LIKE :series
            ORDER BY dbo.Schedule.Date ASC";
    }
    $stmt = $dbh->prepare($sql);
    if (isset($series)) {
        $stmt->execute(array(":series" => $series));
    }
    $stmt->setFetchMode(PDO::FETCH_ASSOC);
    $dbh = null;
}
catch(PDOException $e) {
    echo $e->getMessage();
}

对于任何不包含&的系列标题,它都可以正常使用,但对于任何系列标题都会失败(不会产生任何结果)。

例如,Abounding Ability有效,但接收&部署治疗不会(尽管两者都在数据库的系列字段中。

我单独尝试了htmlspecialchars(rawurlencode($_GET["series"]))和每个人。

在SQL服务器上,传递相同的查询(使用标题)可以正常工作。

SELECT *
FROM [Radio].[dbo].[Schedule]
where Series like 'Receiving & Ministering Healing'

我的猜测是问题在于执行预准备语句或绑定参数。

我在PHP's Prepared Statements page搜索了&,但没有看到任何结果。

修改

我用它来使它工作......

$series = null;
if (isset($_GET["series"])) $series = $_GET["series"];
$queries = parse_url($_SERVER['QUERY_STRING']);
if (substr($queries["path"], 7) == "Receiving%20&%20Ministering%20Healing") $series = "Receiving & Ministering Healing";

我确信这是一种可怕的方式,但没有其他选择可行。当然,这只适用于这种特殊情况。我欢迎更好的解决方案。

编辑2:

我发现WORD系列中的一个系列(Graces And Places)也出现了同样的问题。我最终复制了我对Receiving& amp;的“修复”。为它治疗部长。

我似乎与URL查询(或单词And并不重要)有任何关系,但是准备好的语句。

1 个答案:

答案 0 :(得分:3)

这可能有多种原因。 &字符在多个级别上是邪恶的,在这种情况下,这两个似乎是相关的:

可能是您的请求看起来像这样(&标志突出显示)

http://somedomain.com/somepage.php?param=something&series=Receiving & Ministering Healing
                                                  ^ (valid)         ^ (unintended!)

因为标题未针对网址进行转义。这意味着&字符标记新的参数名称 - 并将series截断为Receiving而不是完整标题Receiving & Ministering,从而导致查询:

SELECT *
FROM [Radio].[dbo].[Schedule]
where Series like 'Receiving '

您可能应该向我们展示如何汇总请求的网址,以便能够推荐更多适当的解决方案,但您应该使用 urlencode() 进行转义要在GET参数中使用的值。

或者问题可能是(但现在不是这种情况)你错误地值。

单个&字符在HTML中无效!正确的转义是&

您应该使用htmlentities对来自 SELECT 查询的输出进行HTML编码:

echo "<h1>".htmlentities($resultComingFromQuery)."</h1>";

修改

错误的请求可能会导致错误的响应(GIGO)......这个:

http://www.flcbranson.org/api/radio/?series=Receiving%20%26%20Ministering Healing

是正确的请求。这是网址编码。你必须解码它:

$decodedTitle = urldecode($_GET['series']);

并在查询中使用它......