我想在PHP中创建一个排序菜单,Symfony可能非常深。 因此我在db(parent_id,sort)类别中添加了2个字段
我的问题是得到像
这样的排序数组array(
//MAIN CATEGORY 1
array(
'id' => 1,
'name' => 'Main',
'child'=> false
),
//MAIN CATEGORY 2
array(
'id' => 2,
'name' => 'Main2',
'child'=> false
),
//MAIN CATEGORY 3
array(
'id' => 6,
'name' => 'Main3',
'child'=> array(
array(
'id' => 4,
'name' => 'Sub of Main3',
'child'=> array(
'id' => 4,
'name' => 'Sub Sub og Main3',
'child'=> false
)
),
array(
'id' => 7,
'name' => '2. Sub og Main3',
'child'=> false
)
)
)
);
所以我可以用它来创建KnpMenu Bundle的菜单。 我找不到另一种方式,性能经济实惠,并且可以使用这个包。
任何人都可以帮助我,如何从数据库中创建数组?
我测试了一些东西并找到了一个像knpMenuBundle这样的解决方案:
namespace AppBundle\Menu;
use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
class Builder implements ContainerAwareInterface
{
use ContainerAwareTrait;
public function mainMenu(FactoryInterface $factory, array $options)
{
$em = $this->container->get('doctrine')->getManager();
$mandant = $this->container->get('session')->get('mandantId');
$nodes = $em->getRepository('AppBundle:Categories')->findSorted($mandant);
$menu = $factory->createItem('root');
$menu->addChild('Startseite', array('route' => 'homepage'));
foreach($nodes as $node)
{
$childMenu = $menu->addChild($node['name'],array('route' => $node['route']));
$this->loadChild($childMenu,$node);
}
return $menu;
}
private function loadChild($childMenu,array $node)
{
if(isset($node['child']))
{
foreach ($node['child'] as $child)
{
$childMenu = $childMenu->addChild($child['name'],array('route' => $child['route']));
$this->loadChild($childMenu,$child);
}
}
return;
}

答案 0 :(得分:0)
我有一个非常类似的问题,这就是我如何解决它。
所以我的页面实体看起来像这样:
<?php
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Knp\Menu\NodeInterface;
/**
* Page
*
* @ORM\Table(name="PAGE")
* @ORM\Entity()
*/
class Page implements NodeInterface
{
/**
* @var int
*
* @ORM\Column(name="ID", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="TITLE", type="string", length=255)
*/
private $title;
/**
* page | link | pdf
* @var string
*
* @ORM\Column(name="CONTENT_TYPE", type="string", length=255)
*/
private $contentType;
/**
* A page can have one parent
*
* @var FacetPage
*
* @ORM\ManyToOne(targetEntity="Page", inversedBy="childrenPages")
* @ORM\JoinColumn(name="PARENT_PAGE_ID", referencedColumnName="ID")
*/
private $parentPage;
/**
* A parent can have multiple children
*
* @var arrayCollection
*
* @ORM\OneToMany(targetEntity="Page", mappedBy="parentPage")
*
*/
private $childrenPages;
/**
* @var resource
*
* @ORM\Column(name="CONTENT", type="text", length=200000)
*/
private $content;
/**
* Many pages could have many allowed roles
*
* @var arrayCollection
*
* @ORM\ManyToMany(targetEntity="Role")
* @ORM\JoinTable(name="PAGE_ALLOWED_ROLES",
* joinColumns={@ORM\JoinColumn(name="page_id", referencedColumnName="ID")},
* inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="ID")}
* )
*/
private $allowedRoles;
/**
* @var string
*
* @ORM\Column(name="SLUG", type="string", nullable=true)
*/
private $slug;
/**
* @var string
*
* @ORM\Column(name="PERMALINK", type="string", nullable=true)
*/
private $permalink;
/**
* @var User
*
* @ORM\ManyToOne(targetEntity="User")
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="CREATED_BY", referencedColumnName="ID", nullable=false)
* })
*
*/
private $author;
/**
* @var \DateTime
*
* @ORM\Column(name="CREATED_ON", type="datetime", nullable=false)
*/
private $createdOn;
/**
* The default status of new pages is published
*
* @var string
*
* @ORM\Column(name="STATUS", type="string", nullable=false, )
*/
private $status = 'published';
/**
* Page constructor.
*/
public function __construct( ) {
//https://knpuniversity.com/screencast/collections/many-to-many-setup#doctrine-arraycollection
$this->allowedRoles = new ArrayCollection();
$this->childrenPages = new ArrayCollection();
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @param int $id
*/
public function setId( int $id )
{
$this->id = $id;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $title
*/
public function setTitle( string $title )
{
$this->title = $title;
}
/**
* @return string
*/
public function getContentType()
{
return $this->contentType;
}
/**
* @param string $contentType
*/
public function setContentType( string $contentType )
{
$this->contentType = $contentType;
}
/**
* @return Page
*/
public function getParentPage()
{
return $this->parentPage;
}
/**
* @param Page $parentPage
*/
public function setParentPage( Page $parentPage )
{
$this->parentPage = $parentPage;
}
/**
* @return string
*/
public function getContent()
{
return $this->content;
}
/**
* @param string $content
*/
public function setContent( string $content )
{
$this->content = $content;
}
/**
* @return ArrayCollection|Role[]
*/
public function getAllowedRoles()
{
return $this->allowedRoles;
}
/**
* @param arrayCollection $allowedRoles
*/
public function setAllowedRoles( $allowedRoles )
{
$this->allowedRoles = $allowedRoles;
}
/**
* @return string
*/
public function getSlug()
{
return $this->slug;
}
/**
* @param string $slug
*/
public function setSlug( string $slug )
{
$this->slug = $slug;
}
/**
* @return string
*/
public function getPermalink()
{
return $this->permalink;
}
/**
* @param string $permalink
*/
public function setPermalink( string $permalink )
{
$this->permalink = $permalink;
}
/**
* @return User
*/
public function getAuthor()
{
return $this->author;
}
/**
* @param FacetUser $author
*/
public function setAuthor( User $author )
{
$this->author = $author;
}
/**
* @return \DateTime
*/
public function getCreatedOn()
{
return $this->createdOn;
}
/**
* @param \DateTime $createdOn
*/
public function setCreatedOn( \DateTime $createdOn )
{
$this->createdOn = $createdOn;
}
/**
* @return string
*/
public function getStatus()
{
return $this->status;
}
/**
* @param string $status
*/
public function setStatus( string $status )
{
$this->status = $status;
}
/**
* @return ArrayCollection
*/
public function getChildrenPages()
{
return $this->childrenPages;
}
/**
* @param ArrayCollection $childrenPages
*/
public function setChildrenPages( $childrenPages )
{
$this->childrenPages = $childrenPages;
}
/**
* Get the name of the node
*
* Each child of a node must have a unique name
*
* @return string
*/
public function getName() {
return $this->title;
}
/**
* Get the options for the factory to create the item for this node
*
* @return array
* @throws \Exception
*/
public function getOptions() {
if($this->contentType == 'page'){
return [
'route' => 'core_page_id',
'routeParameters' => ['id'=>$this->id]
];
}
if($this->contentType == 'doc'){
return [
'uri'=>'/'.$this->getContent()
];
}
if($this->contentType == 'link'){
return [
'uri'=>$this->content
];
}
throw new \Exception('No valid options found for page type',500);
}
/**
* Get the child nodes implementing NodeInterface
*
* @return \Traversable
*/
public function getChildren() {
return $this->getChildren();
}
}
这里的主要区别在于它实现了Knp的NodeInterface及其在实体末尾定义的函数,getName(),getOptions()和getChildren()。
现在进入我的构建器,它基本上和你的递归函数做同样的事情。
<?php
namespace AppBundle\Menu;
use AppBundle\Entity\Page;
use Knp\Menu\FactoryInterface;
use Knp\Menu\ItemInterface;
use Knp\Menu\MenuItem;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
class Builder implements ContainerAwareInterface
{
use ContainerAwareTrait;
/** @var ItemInterface */
private $menu;
/**
* @param FactoryInterface $factory
* @param array $options
*
* @return ItemInterface
*/
public function mainMenu(FactoryInterface $factory, array $options)
{
$this->menu = $factory->createItem('root');
$this->menu->addChild('Home', array('route' => 'core_homepage'));
$em = $this->container->get('doctrine')->getManager();
// get all published pages
$pages = $em->getRepository(Page::class)->findBy(['status'=>'published']);
// build pages
try {
$this->buildPageTree( $pages );
} catch ( \Exception $e ) {
error_log($e->getMessage());
}
return $this->menu;
}
/**
*
* @param array $pages
* @param Page $parent
* @param MenuItem $menuItem
*
* @throws \Exception
*/
private function buildPageTree(array $pages, $parent = null, $menuItem = null)
{
/** @var Page $page */
foreach ($pages as $page) {
// If page doesn't have a parent, and no menuItem was passed then this is a top level add.
if(empty($page->getParentPage()) && empty($menuItem) )
$parentMenu = $this->menu->addChild($page->getTitle(), $page->getOptions());
// if the current page's parent is === supplied parent, go deeper
if ($page->getParentPage() === $parent) {
// if a menuItem was given, then this page is a child so added it to the provided menu.
if(!empty($menuItem))
$parentMenu = $menuItem->addChild($page->getTitle(), $page->getOptions());
// go deeper
$this->buildPageTree($pages, $page, $parentMenu);
}
}
}
}
我希望这在某种程度上有所帮助!