Breadcrumb navigation with Doctrine NestedSet

社会主义新天地 提交于 2019-12-02 22:22:21

问题


I have a model that implements NestedSet behaviour:

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

Example fixtures:

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

I am looking for the easiest way to implement breadcrumb navigation (trail). For example, for Page_3 navigation will look like this:

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

回答1:


Almost the same as in the other question, but you have to add a 'parentUrl' variable :

//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;

Feed it the root of your tree as $node (hydrate it hierarchically), the node of the current page as $pageNode, and '' as $currentNodeUrl and add ' > ' and the link to the current page.

Why does this solution use recursion and not getAncestors()? Because your urls seem to imply recursion.




回答2:


Since I hate having any kind of logic in templates (and partials), here's my slightly improved version.

//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; ?>

So, all the logic for building a url is now in Page::getPath() method.

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;
  } 
}

What I don't like it having to pass $parent to Page::getPath(). It just doesn't make any semantical sense.




回答3:


Another answer, more simple (and perhaps more efficient), with getAncestors() and recursion:

//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));
}

Call this with an array of ancestor nodes or find a way to pop a Doctrine_Collection if you want to use it with getAncestors() directly. Again, all your problem comes from the fact that your urls are recursively computed, it would be simpler and faster to display if you had a colum path with the current url (but then you would have to compute, update it), etc... consider doing this if you have more reads than writes (if your tree does not change often).



来源:https://stackoverflow.com/questions/6009163/breadcrumb-navigation-with-doctrine-nestedset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!