Welcome to php club

PHP FAQ from PHPclub.ru: Tree/DemoPathid ...

Начало | Каталог | Изменения | НовыеКомментарии | Вам запрещён доступПользователи | Вам запрещён доступРегистрация | Вход:  Пароль:  

Деревья в базах данных => Примеры скриптов => Id раздела по URL

Как найти id раздела по URL


В базе хранятся в виде Nested Sets разделы сайта. Пользователь набрал скажем /info/news/archive/. Как наиболее эффективно вычислить id этого раздела?


Для решения этой задачи важна ТОЛЬКО возможность быстрой проверки, является ли одна вершина непосредственным ребенком другой. Эта проверка выполняется одинаково быстро как в списках смежности, так и во вложенных множествах. Поэтому c точки зрения быстродействия для решения этой задачи не имеет никакого значения, хранятся ли деревья в виде Nested Sets, либо они хранятся в виде Adjacency Lists.


На вход следующей функции подается путь (строка) в виде:
/info/news/archive/
/info/news/archive
info/news/archive/
/info/news/archive/index.html
это все ссылка на один и тот же файл: слеш в конце и в начале может быть, а может не быть. Путь, который заканчивается на “index.html” – индексный файл для каталога, который обычно содержит в себе то же, что и сам каталог.


Функция text_top_id() возвращает идентификатор самого верхнего узла дерева.


В таблице t_text_data хранится описание вершины дерева (имя файла – s_file, идентификатор текста – k_text). В этой таблице должен быть индекс по полю s_file.


В таблице t_text_tree хранится собственно дерево Nested Set (i_id – идентификатор вершины, который соответствует идентификатору текста k_text; i_left, i_right – левое и правое значение узла; i_level – уровень).


<?php
function text_file_path($s_path)
{
  if(!
is_string($s_path)) return false;
  if(
substr($s_path,-10)=='index.html')
    
$s_path=substr($s_path,0,-10);
  if(
substr($s_path,-5)=='.html')
    
$s_path=substr($s_path,0,-5);
  if(
substr($s_path,-1)=='/')
    
$s_path=substr($s_path,0,-1);
  if(
strlen($s_path)&&$s_path[0]=='/')
    
$s_path=substr($s_path,1);

  if(!
strlen($s_path)) return array(text_top_id());

  
$p=explode('/',$s_path);

  
$s='r0.i_id';
  
$t='';
  
$w='r0.i_id='.text_top_id();
  for(
$i=0;$i<count($p);$i++)
  {
    
$c=$i+1;
    
$s.=',r'.$c.".i_id";
    
$t.=',t_text_data as t'.$c.",t_text_tree as r".$c;
    
$w.=" and t".$c.".s_file='".addslashes($p[$i])."'
          and t"
.$c.".k_text=r".$c.".i_id
          and r"
.$c.".i_left between r".$i.".i_left+1 and r".$i.".i_right
          and r"
.$c.".i_level=r".$i.".i_level+1";
  }
  
$r=mysql_query("select ".$s." from t_text_tree as r0".$t." where ".$w." limit 1");
  if(!
$r||!mysql_num_rows($r)) return false;
  return 
mysql_fetch_assoc($r);
}
?>


Замечание Эта функция работает на деревьях с ограниченной глубиной вложенности. Ограничение связано с количеством таблиц, которые можно использовать в разделе FROM оператора SELECT.


 
Один комментарий. [Показать комментарии/форму]