Структура Traverse Doctrine NestedSet без запросов - PullRequest
2 голосов
/ 14 мая 2011

Я обычно выбираю дерево NestedSet следующим образом:

class ModelTable extends Doctrine_Table
{
  /**
   * Gets tree elements in one query
   */
  public function getMenuTree()
  {
    $q = $this->createQuery('p')
      ->orderBy('p.root_id')
      ->addOrderBy('p.lft');

    $tree = $q->execute(array(),  Doctrine_Core::HYDRATE_RECORD_HIERARCHY);      

    return $tree;
  }
}

Таким образом, я могу фактически отобразить все дерево, используя только один запрос к базе данных ... пока я не попытаюсь пройти по дереву.Например, если вы вызываете метод на узле, подобном этому:

$node->getNode()->getAncestors()

Doctrine создаст для этого совершенно новый запрос (взгляните на Doctrine_Node_NestedSet :: getAncestors ()).Другие методы обхода, такие как getChildren (), также используют DQL.Но это несколько неэффективно, не так ли?После того, как я получил целое дерево, я больше не хочу запрашивать базу данных.

Может, кто-то написал драйвер, чтобы сделать это правильно?(без DQL)

1 Ответ

3 голосов
/ 15 мая 2011

Если вы хотите получить только дочерние элементы (что наиболее вероятно, зачем вам нужно getAncestors() для итерации по дереву?), Вы также можете сохранить код, который вы показали нам в качестве примера, и сделать что-то подобноеэто:

foreach ($categories->getFirst()->get('__children') as $child) {
    // ...
}

Это задокументировано здесь (трудно найти, если вы не решите прочитать всю документацию).

Однажды я использовал рекурсивный код в целомДерево только с ОДНЫМ запросом.

1015 lib % ack --type="php" "_node"                                                                                                                                                          2011-05-15 14:26:22 greg pts/1
vendor/doctrine/Doctrine/Record.php
94:    protected $_node;
814:        unset($vars['_node']);
2403:        if ( ! isset($this->_node)) {
2404:            $this->_node = Doctrine_Node::factory($this,
2410:        return $this->_node;
liche ~/source/symfony/1.4/lib/plugins/sfDoctrinePlugin/lib

_node, кажется, установлен только в самом getNode(), я не знаю, можете ли вы гидрировать его как любое другое поле, или как вы это сделаете.

Я думаю, что getNode() следует использовать только для модификации дерева.Если вы хотите отобразить путь от корня, вы должны использовать рекурсивный метод для отображения дерева с аргументом, содержащим путь родителя.Если есть что-то еще, для чего вам понадобится древовидная функциональность, сообщите нам ...

ОБНОВЛЕНИЕ

Я думаю, что в конце концов получил это.Вы хотите отобразить древовидное меню И хлебную крошку, и вы хотите повторно использовать данные меню в хлебной крошке, не так ли?Чтобы отобразить свои хлебные крошки, вы должны вернуться к $ tree и отобразить узел тогда и только тогда, когда он является предком текущей страницы.И есть способ для этого: isAncestorOf().Таким образом, «все, что вам нужно сделать» - это шаблон, который выполняет что-то вроде этого:

//module/templates/_breadcrumbElement.php
foreach ($node->get('__children') as $child) :
  if ($child->isAncestorOf($pageNode)):
     echo link_to($child->getName(), $child->getUrl());
     include_partial('module/breadcrumbElement', array('node' => $child, 'pageNode' => $pageNode));
  endif;
endforeach;

Накормите его корнем вашего дерева, и все будет в порядке.Будем надеяться.

...