在您的IN 条件中引用静态值在“稳定性”和“安全性”方面完全没有用。这些数据点不是注入攻击向量,因为它们是静态的。您的查询没有中断的风险,因为您已正确写入整数值。引用数组值只会增加不必要的代码膨胀,导致效率略有下降,并使您的代码更难阅读。
在 Joomla Stack Exchange 的 How to Use IN Clause in Joomla Query 上查看我非常全面的答案。
相反,您的查询可以安全/可靠地写成:
$query = $db->getQuery(true)
->select(["id", "a.promo", "a.harga", "a.dp", "a.image", "a.teaser", "a.title", "a.created"])
->from("#__cck_store_form_paket_trip a")
->innerJoin("#__content b USING (id)")
->where("b.catid IN (13,14,15)")
->order($db->qn($orderby) . ($order == "DESC" ? " DESC" : ''))
->setLimit($limit, $start);
解释:
-
select() 方法不包含任何 MySQL 关键字或猴子扳手字符,因此不需要引用/转义这些静态值。
-
from() 方法不需要 qn() 出于同样的原因。
- 使用 Joomla 略短的
leftJoin() 而不是长手 join('LEFT',...) 语法。更好的是,因为您的 WHERE 要求取消了连接到 b 中 null 行的任何 a 行,所以使用 innerJoin() 更合适。
- 由于两个表中要连接的列具有相同的名称,您可以享受
USING 更甜美的语法。这也意味着您在查询中的其他位置引用 id 时无需指定表别名。
-
where() 方法,正如我文章开头提到的,可以静态编写。即使您传入一个您之前在脚本中静态编写的数组,您也可以像这样安全地使用它:
->where("b.catid IN (" . implode(',', $arrayOfIntegers) . ")")
因为可以安全地假设$orderby 是从用户输入派生的,所以您应该继续在order() 方法中实现qn()。因为ASC是默认的排序方向,所以我只在查询中有条件地写DESC(IOW,如果排序方向是ASC,就省略)。
-
setLimit() 可以满足您的要求,因为该方法经过硬编码,可通过 Joomla 将传入的值转换为整数。
如果您想查看生成的 sql 查询,请使用:
echo $query->dump();
要运行基本诊断检查,您可以使用以下命令,但永远不要向公众显示 $query->dump() 或原始 $e->getMessage() 字符串!
// never show $query->dump() to the public
JFactory::getApplication()->enqueueMessage($query->dump(), 'info');
$db->setQuery($query);
try {
if (!$result = $db->loadAssocList()) {
echo "No Qualifying Rows";
} else {
echo "<table>";
echo "<tr><th>", implode("</th><th>", array_keys($result[0])), "</th></tr>";
foreach ($result as $row) {
echo "<tr><td>", implode("</td><td>", $row), "</td></tr>";
}
echo "</table>";
}
} catch (Exception $e) {
// never show getMessage() to the public
JFactory::getApplication()->enqueueMessage("Query Syntax Error: " . $e->getMessage(), 'error');
}