Доктрина 1.2. Свойства NestedSet и наследование отношений от предков
У меня есть проект Doctrine 1.2, который я реорганизую, чтобы иметь древовидную структуру для таблицы, использующей поведение доктрины NestedSet с несколькими корнями.
Что мне нужно, так это наследование (не в здравом смысле ОО) от предков к потомкам, в котором потомки наследуют свойства от ближайшего предка, где их собственные свойства отсутствуют. То же самое произошло бы с отношениями.
Позвольте мне объяснить на примере:
Category:
actAs:
NestedSet:
hasManyRoots: true
rootColumnName: root_id
columns:
name: string(50)
another_property: string(50)
active: boolean
Tag:
columns:
value: string(50)
CategoryTag:
columns:
category_id: integer
tag_id: integer
То, что я хочу выполнить, это:
- Получить, если категория активна, это означает, что все предки активны.
- если для данной категории отсутствует another_property, унаследуйте ее от ближайшего предка, в котором присутствует
- получить теги для данной категории; если теги отсутствуют, извлеките их у ближайшего предка
Что бы вы предложили в качестве наилучшего подхода для максимизации скорости и гибкости?
1 ответ
Ну, это очень просто. Просто получите дерево с нужными вам отношениями вот так:
class ModelTable extends Doctrine_Table
{
/**
* Gets tree element in one query
*/
public function getModelTree()
{
$q = $this->createQuery('g')
->leftJoin('g.Tags t')
->orderBy('g.root_id')
->addOrderBy('g.lft')
->where('g.root_id NOT NULL')
;
return $q->execute(array(), Doctrine_Core::HYDRATE_ARRAY_HIERARCHY);
}
}
Затем вы можете сделать это так:
<?php function echoNode($tree, $parent=null) { ?>
<ul>
<?php foreach ($tree as $node): ?>
<li data-property='<?php echo false != $node['property'] ? $node['property'] : $parent['property'] ?>'>
<?php echo $node['name'] ?>
<?php if (count($node['__children']) > 0): ?>
<?php echo echoNode($node['__children'], $node) ?>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php } ?>
<?php echo echoNode($tree) ?>
Обратите внимание, как вы можете получить свойство из родительского узла, если оно отсутствует. Другой способ решения этой проблемы - использовать Doctrine_Core::HYDRATE_RECORD_HIERARCHY. Это позволяет использовать для вызова методов на $ узлах при цикле. Вы можете создать метод Model::getClosestProperty(), например, чтобы получить свойство от ближайшего родителя. Но это не так эффективно, как увлажнение массива.