2013-11-01 2 views
0

Я пытаюсь определить, на какой странице пользователь включен, используя URL-адреса 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); 
} 

Целью этого метода является просмотр иерархии страниц и проверка правильности его. Проблема, однако, состоит в том, что, поскольку иерархия представлена ​​как URL SEF, например path/to/page/module/action/123, в какой-то момент элементы в вышеупомянутой строке больше не представляют страницы, а другие переменные.

Если я подаю всю цепочку 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 вроде объединял то, что он мог, и пренебрегает остальными? Вместо того, чтобы заявить: «Я собираюсь рассказать вам, если эта иерархия страниц действительна», этот метод, который я описал, должен содержать следующее сообщение: «Я собираюсь рассказать вам, КОТОРЫЙ ТОЧКА эта иерархия страницы действительна».

Любая помощь приветствуется.

ответ

2

Проблема заключается в том, что, хотя вы используете LEFT JOIN, поскольку вы указываете значение для каждой таблицы в предложении WHERE, вы вынуждаете каждую таблицу иметь запись, которая отображает результат, который будет таким же, как ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

Таким образом, изменение

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

в

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

Это позволит вам воспользоваться LEFT JOIN и «пропустить» таблицы, которые не совпадают, в то же время возвращать результаты для чего найден.

Ваш SELECT затем вернет id s для найденных страниц, а затем null для остальных значений, которые не соответствуют странице.

Смежные вопросы