Навигация по сухарям с помощью Doctrine NestedSet - PullRequest
0 голосов
/ 15 мая 2011

У меня есть модель, которая реализует поведение NestedSet:

Page:
  actAs:
    NestedSet:
      hasManyRoots: true
      rootColumnName: root_id
  columns:
    slug: string(255)
    name: string(255)

Пример приборов:

Page:
  NestedSet: true
  Page_1:
    slug: slug1
    name: name1
  Page_2:
    slug: slug2
    name: name2
    children:
      Page_3:
        slug: page3
        name: name3

Я ищу самый простой способ реализовать навигацию крошки (след).Например, для Page_3 навигация будет выглядеть так:

<a href="page2">name2</a> > <a href="page2/page3>name3</a>

Ответы [ 3 ]

1 голос
/ 15 мая 2011

Так как я ненавижу иметь какую-либо логику в шаблонах (и частичных), вот моя слегка улучшенная версия.

//module/templates/_breadcrumbElement.php
<?php foreach ($node as $child): ?>
<li>
  <a href="<?php echo $child->getPath($parent) ?>"><?php echo $child->getName() ?></a>
  <?php if (count($child->get('__children')) > 0): ?>
    <ul>
      <?php include_partial('node', array('node' => $child->get('__children'), 'parent' => $child)) ?>
    </ul>
  <?php endif; ?>
</li>
<?php endforeach; ?>

Итак, вся логика для создания URL теперь находится в методе Page :: getPath ().

class Page extends BasePage
{
  /**
   * Full path to node from root
   *
   */
  protected $path = false;

  public function __toString()
  {
    return $this->getSlug();
  }
  public function getPath($parent = null)
  {
    if (!$this->path)
    {
      $this->path = join('/', null !== $parent ? array($parent->getPath(), $this) : array($this));
    }
    return $this->path;
  } 
}

Что мне не нравится, так это передача $ parent в Page :: getPath (). Это просто не имеет никакого семантического смысла.

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

Другой ответ, более простой (и, возможно, более эффективный), с getAncestors () и рекурсией:

//module/templates/_breadcrumbElement.php
if ($node = array_pop($nodes)) // stop condition
{
    $currentNodeUrl = $parentUrl . $node->getSlug() . '/';
    echo link_to($node->getName(), $currentNodeUrl) . ' > ' ;
    include_partial('module/breadcrumbElement', array(
      'nodes' => $nodes, 'parentUrl' => $currentNodeUrl));
}

Назовите это с массивом узлов-предков или найдите способ получить Doctrine_Collection, если вы хотите использовать его с getAncestors() напрямую. Опять же, вся ваша проблема связана с тем, что ваши URL рекурсивно вычисляются, было бы проще и быстрее отображать их, если бы у вас был путь столбца с текущим URL (но тогда вам пришлось бы вычислять, обновлять его) и т. . подумайте об этом, если у вас больше операций чтения, чем записи (если ваше дерево меняется не часто).

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

Почти так же, как и в другом вопросе, но вы должны добавить переменную parentUrl:

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

Подать корень дерева как $node (иерархически гидратировать),узел текущей страницы как $pageNode, а '' как $currentNodeUrl и добавление '>' и ссылка на текущую страницу.

Почему в этом решении используется рекурсия, а не getAncestors()?Потому что ваши URL, кажется, подразумевают рекурсию.

...