0

我正在尝试使用 SEF URL 确定用户在哪个页面上。它是这样工作的:

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('/')前面提到的字符串中的项目不再代表页面,而是其他变量。

如果我将整个字符串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 加入它可以加入的东西而忽略其余部分?而不是说“我要告诉你这个页面层次结构是否有效”,我描述的这个方法应该声明“我要告诉你这个页面层次结构在哪一点是有效的”。

任何帮助表示赞赏。

4

1 回答 1

2

问题是,虽然您使用的是 LEFT JOIN,但由于您在 WHERE 子句中为每个表指定了一个值,因此您强制每个表都有一条记录,这会呈现与 INNER JOIN 相同的结果。

因此,改变

$where .= "t$i.alias = ?";

$where .= "(t$i.alias = ? OR t$i.id IS NULL)";

这将允许您利用 LEFT JOIN 并“跳过”不匹配的表,同时仍返回找到的结果。

然后,您的 SELECT 将为id找到的那些页面返回 s,然后为与页面不对应的剩余值返回 null。

于 2013-11-01T07:44:54.877 回答