我正在尝试使用SEF网址确定用户所在的页面。它的工作原理如下:
public function getIdsByPath(array $path, $langId) {
$select = 'SELECT ';
$from = ' FROM pages t0 ';
$where = 'WHERE ';
for($i = 0; $i < count($path); $i++) {
$ii = $i - 1;
if($i > 0) {
$select .= ', ';
$from .= "LEFT JOIN pages t$i ON (t$i.pid = t$ii.id) ";
$where .= ' AND ';
}
$select .= "t$i.id";
$where .= "t$i.alias = ?";
}
$where .= " AND t0.pid = ?";
$q = $this->db->prepare($select.$from.$where);
for($i = 0; $i < count($path); $i++) {
$q->bindValue($i + 1, $path[$i]);
}
$q->bindValue($i + 1, $langId);
$q->execute();
return $q->fetch(PDO::FETCH_NUM);
}
此方法的目的是浏览页面层次结构并验证它是否正确。但问题是,由于层次结构显示为SEF URL,如path/to/page/module/action/123
,explode('/')
'前面提到的字符串中的项目不再代表页面,而是其他变量。< / p>
如果我将整个字符串path/to/page/module/action/item/123
提供给方法,则查询将找不到任何内容,因为JOIN
语句。我试过了其他所有JOIN
我也能想到的。所有人都确定,因为没有找到所有的东西,所以没有找到期间。
如果首先通过关键字从URL检测到其他变量,则整个方法可以很好地工作,但这会导致更详细的URL,这是我不想要的。 path/to/page/some-module/edit/123
会变为path/to/page/module/some-module/action/edit/item/123
。不太好。
有没有办法JOIN
的东西,以便MySQL加入它可以和忽略其余的东西?我没有说“如果这个页面层次结构有效,我将告诉你”这个方法应该说明“我将告诉你这个页面层次结构是有效的。”
任何帮助表示感谢。
答案 0 :(得分:2)
问题在于虽然您使用的是LEFT JOIN,但由于您在WHERE子句中为每个表指定了一个值,因此您强制每个表都有一个记录,这会产生与INNER相同的结果。 JOIN。
因此,改变
$where .= "t$i.alias = ?";
到
$where .= "(t$i.alias = ? OR t$i.id IS NULL)";
这将允许您利用LEFT JOIN并“跳过”不匹配的表格,同时仍然返回找到的结果。
然后,您的SELECT将返回找到的那些页面的id
,然后为与页面不对应的其余值返回null。