Показ дописів із міткою Symfony. Показати всі дописи
Показ дописів із міткою Symfony. Показати всі дописи

четвер, березня 26, 2009

Nested Set Symfony или CodeIgniter

symfonyО проблемах хранения деревьев в SQL базах данных вопрос можно не поднимать, просто сказать, что они есть. Теорию, посвященную описанию этих деревьев и как организована структура в базе данных, можно найти на сайте Wikipedia. В данном же посте я опишу свой класс, который я разработал для манипулирования Nested Set в Doctrine для CodeIgniter или Symfony. При помощи этого класса, можно не задумываясь вставлять, удалять, перемещать ноды дерева. Класс писался с прицелом, на то, что его можно будет легко заменить другим классом, не работающим с Nested Set, но предоставляющим такой же API. Также важная поправка, класс писался используя плагин к Doctrine Nested Set.
Первое, что я создал для класса вложенных множеств это его интерфейс:
interface Hierarchical
{
public function build($object);
public function _getTree();
public function _getBranch($branch = 0);
public function _add($parent);
public function _delete($id);
public function _replace($parent,$id);
}
Благодаря интерфейсу, иной класс, наследуя его может с легкостью заменить класс вложенных множеств.

Сам класс выглядит так:
class NestedSet extends Doctrine_Record implements Hierarchical
{
public function build($object)
{
$this->iObject = $object;
$this->Object = Doctrine::getTable($this->TABLE_NAME)->getTree();
$this->hasManyRoots = $this->Object->getAttribute('hasManyRoots');
}

public function _getTree()
private function getChildren($item)
public function _getBranch($branch = 0)
public function _add($parent)
public function _delete($id)
public function _replace($parent,$id)
}
Зная, о том, что деревья могут содержать несколько рутовых веток или одну рут-ветку некоторые функции учитывают эту особенность.

Функция получения Дерева в Nested set:
public function _getTree()
{
$this->TreeArray = array();

if ($this->hasManyRoots)
{
$rootColumnName = $this->Object->getAttribute('rootColumnName');
foreach ($this->Object->fetchRoots() as $root)
{
$options = array('root_id'=>$root->$rootColumnName);
foreach($this->Object->fetchTree($options)->toArray() as $node)
{
$this->TreeArray[$root->$rootColumnName][] = $node;
}
}
}
else
{
foreach ($this->Object->fetchTree()->toArray() as $node)
{
$this->TreeArray[$node['level']][] = $node;
}
}
return $this->TreeArray;
}
Как видно из кода все ясно и понятно.

Особенности создания правильной структуры Nested Set, и как создавать Many Roots деревья используя Doctrine yaml в схемах, я опишу немного позже.

Вот основная функция, которая работают с деревом Nested Set в Symfony и в CodeIgniter используя PHP ORM Doctrine плагин. Сам класс получился довольно простым и дееспособным. Остальные функции, выложить не удалось из-за нечитабельного их расположения на страницах блога (код вылазит за границы страницы и надо его вручную подгонять, а мне лень).
Весь код класса я могу выложить сюда же в блог, по первому требованию девелоперов, для того, что бы сократить время затраченное на разработку тех или иных задач, в которых используется NestedSet.

Основную информацию по легкому созданию и управлению деревьями вы можете взять отсюда и написать свой собственный класс.

В дальнейшем я планирую написать легкое и доступное овервью как создавать деревья посредством Doctrine yaml схем, и как использовать SimpleTest в Doctrine для методики TDD.
Также хочу насторожить тех девелоперов, которые впервые работают с Nested Set. Переход от структуры смежных вершин к вложенному множеству влечет за собой некий дискомфорт ))).

Що таке база данних?

База данних — це спеціальна система зберігання, організації та пошуку інформації. Вона містить дані у вигляді таблиць, записів та інших стру...