我有一大堆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并不重要)有任何关系,但是准备好的语句。
答案 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']);
并在查询中使用它......