Reputation: 1964
I've built a menu using knpmenubundle, it's working really well and pulling the navigation dynamically from the database. However the client now wants to add a submenu to it. I've written a controller which will find child pages, however I can't see how I can attach them to the subnavigation under the correct parent. At the moment all it does it attach a copy of the current element to itself as a child node.
Here is the menu builder:
$sector = $options['sector'];
$em = $this->getDoctrine()->getManager();
$navItems = $this->getDoctrine()
->getRepository('acmeStyleGuideBundle:pageSector')
->findBySectorJoinedToUrl($sector);
if (!$navItems) throw $this->createNotFoundException('Unable to find any matching pages');
$menu = $factory->createItem('root');
foreach ($navItems as $nav)
{
// Doesn't have any parents, This is a top level
$parent = $menu->addChild($nav->getPageName(), array(
'route' => 'acme_style_guide_pages_show',
'routeParameters' => array(
'sector' => $sector,
'pageUrl' => $nav->getPageUrl()
)
));
$parent->addChild($nav->getPageName(), array(
'route' => 'acme_style_guide_pages_show_sub',
'routeParameters' => array(
'sector' => $sector,
'pageParent' => $nav->getPageName(),
'pageUrl' => $nav->getPageUrl()
))
);
}
Here is the controller for the parent element:
// Render pages from database
public function showAction($sector, $pageUrl)
{
$em = $this->getDoctrine()->getManager();
$pages = $this->getDoctrine()
->getRepository('acmeStyleGuideBundle:PageContent')
->findByUrlJoinedToSector($sector, $pageUrl);
if (!$pages) throw $this->createNotFoundException('Unable to find any matching pages');
return $this->render(
'acmeStyleGuideBundle:Page:pages.html.twig',
array(
'Pages' => $pages,
'sector' => $sector
)
);
}
and here is the controller for the child element:
// Render sub pages from database
public function showSubAction($sector, $pageParent, $pageUrl)
{
$em = $this->getDoctrine()->getManager();
$pages = $this->getDoctrine()
->getRepository('acmeStyleGuideBundle:PageContent')
->findByUrlJoinedToSectorAndParent($sector, $pageParent, $pageUrl);
if (!$pages) throw $this->createNotFoundException('Unable to find any matching pages');
return $this->render(
'acmeStyleGuideBundle:Page:pages.html.twig',
array(
'Pages' => $pages,
'sector' => $sector
)
);
}
Both of these controllers pull information from the database using a custom repository class.
Here is the custom repository code:
public function findByUrlJoinedToSector($sector, $pageUrl)
{
$query = $this->getEntityManager()
->createQuery('
SELECT p, s FROM acmeStyleGuideBundle:PageContent p
JOIN p.pageSector s
LEFT JOIN p.pageTypes t
WHERE p.pageUrl = :url
AND s.sectorName = :sector
AND t.typeName != :type'
)
->setParameter('url', $pageUrl)
->setParameter('sector', $sector)
->setParameter('type', 'Section Headers');
try {
return $query->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}
public function findByUrlJoinedToSectorAndParent($sector, $pageParent, $pageUrl)
{
$query = $this->getEntityManager()
->createQuery('
SELECT p, s, c FROM acmeStyleGuideBundle:PageContent p
JOIN p.pageSector s
LEFT JOIN p.pageTypes t
LEFT JOIN p.PageParent c
WHERE p.pageUrl = :url
AND s.sectorName = :sector
AND c.pageUrl = :parent
AND t.typeName != :type'
)
->setParameter('url', $pageUrl)
->setParameter('sector', $sector)
->setParameter('parent', $pageParent)
->setParameter('type', 'Section Headers');
try {
return $query->getResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return null;
}
}
It could be just a Monday morning issue, so I'll keep trying to work it out myself, if I do I will post it here as an answer.
Additional info
Updated builder // find all items with parents. Then attach the found item to its parent. $subNavItems = $this->getDoctrine() ->getRepository('acmeStyleGuideBundle:pageSector') ->findSubNav($sector, $nav->getPageParent());
// loop over them and add a link for each one:
foreach ($subNavItems as $child) {
if ($child->getPageParent() != NULL) {
$parent->addChild($child->getPageName(), array(
'route' => 'acme_style_guide_pages_show_sub',
'routeParameters' => array(
'sector' => $sector,
'pageParent' => $child->getPageName(),
'pageUrl' => $child->getPageUrl()
)
)
);
}
}
}
It's outputting:
<ul>
<li><a href="link">Target Item</a></li>
<li><a href="link">Item</a></li>
<li><a href="link">Item</a></li>
<li><a href="link">Child</a>
<ul>
<li><a href="link">Child</a></li>
</ul>
</li>
</ul>
Whereas I need it to output:
<ul>
<li><a href="link">Target Item</a>
<ul>
<li><a href="link">Child</a></li>
</ul>
</li>
<li><a href="link">Item</a></li>
<li><a href="link">Item</a></li>
<li><a href="link">Child</a></li>
</ul>
This is the schema for the PageContent table
<database name="styleguide">
<!-- Table PageContent -->
<table name="PageContent">
<column name="id">1</column>
<column name="pageTypesId">2</column>
<column name="pageName">Text Elements</column>
<column name="pageUrl">text-elements</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">2</column>
<column name="pageTypesId">2</column>
<column name="pageName">Buttons</column>
<column name="pageUrl">buttons</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">3</column>
<column name="pageTypesId">2</column>
<column name="pageName">Forms</column>
<column name="pageUrl">forms</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">4</column>
<column name="pageTypesId">2</column>
<column name="pageName">Lists</column>
<column name="pageUrl">lists</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">5</column>
<column name="pageTypesId">2</column>
<column name="pageName">Tables</column>
<column name="pageUrl">tables</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">6</column>
<column name="pageTypesId">2</column>
<column name="pageName">Search Box</column>
<column name="pageUrl">search-box</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">7</column>
<column name="pageTypesId">2</column>
<column name="pageName">Pods</column>
<column name="pageUrl">pods</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">8</column>
<column name="pageTypesId">3</column>
<column name="pageName">Business</column>
<column name="pageUrl">business</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">9</column>
<column name="pageTypesId">3</column>
<column name="pageName">Residential</column>
<column name="pageUrl">residential</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">NULL</column>
</table>
<table name="PageContent">
<column name="id">10</column>
<column name="pageTypesId">1</column>
<column name="pageName">Paragraphs</column>
<column name="pageUrl">paragraphs</column>
<column name="richText"><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p></column>
<column name="PageParent">1</column>
</table>
</database>
Upvotes: 0
Views: 1053
Reputation: 6410
You need to loop over all subElements
and render a navigation link for each:
foreach ($navItems as $nav)
{
// Doesn't have any parents, This is a top level
$parent = $menu->addChild($nav->getPageName(), array(
'route' => 'acme_style_guide_pages_show',
'routeParameters' => array(
'sector' => $sector,
'pageUrl' => $nav->getPageUrl()
)
));
// find all sub-items:
$subNavItems = $this->getDoctrine()
->getRepository('acmeStyleGuideBundle:pageSector')
->findByUrlJoinedToSectorAndParent($sector, $parent, /* $pageUrl */);
// loop over them and add a link for each one:
foreach ($subNavItems as $child) {
$parent->addChild($child->getPageName(), array(
'route' => 'acme_style_guide_pages_show_sub',
'routeParameters' => array(
'sector' => $sector,
'pageParent' => $child->getPageName(),
'pageUrl' => $child->getPageUrl()
))
);
}
}
Upvotes: 1