lch / menu-bundle
为 Symfony 提供了一个简单的类似 WordPress 的菜单管理系统
1.2.2
2020-09-09 09:43 UTC
Requires
- php: ^7.0
- knplabs/doctrine-behaviors: ^2.0
- lch/components-bundle: ^1.2
- symfony/framework-bundle: ^4.2
- symfony/translation: 4.4.*
- twig/extensions: ^1.5
Requires (Dev)
- doctrine/doctrine-bundle: ^1.3
- phpunit/phpunit: ~4.8|~5.0
Conflicts
- symfony/doctrine-bridge: <2.7
README
这提供了一个基于 WordPress 理念的简单菜单项处理。你定义 菜单位置,然后使用 Twig 扩展检索分配到该位置的菜单项。
在 BO 的项目编辑部分,该扩展提供了 MenuType
和 CSS/JS 部分,用于拖放功能。
此扩展包支持翻译,使用 lch/translatable-bundle。
安装
composer require lch/menu-bundle "^1.1.8"
配置
安装后,在 config/packages
中创建一个 lch_menu.yaml
文件。你现在可以定义你的 菜单位置,例如
lch_menu: locations: header: title: Header main: title: Main navigation footer_buttons: title: Footer - buttons footer_left: title: Footer - left # ...
管理部分
这完全取决于你,但你在 CRUD 中必须使用 Lch\MenuBundle\Entity\Menu
类。以下是一个 CRUD 示例
namespace App\Controller\Admin; use App\Form\Type\Extension\MenuTypeExtension; use App\Repository\MenuRepository; use Lch\MenuBundle\Entity\Menu; use Lch\MenuBundle\Form\MenuType; use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; /** * @Route("/admin/menu") * @IsGranted("ROLE_ADMIN") */ class MenuController extends AbstractController { /** * @Route( * "/{page}", * name="admin.menu.list", * requirements={"page"="[1-9]\d*"}, * defaults={"page"=1} * ) * * @param int $page * * @return Response */ public function list(int $page): Response { $nbItemsPerPage = 20; /** @var MenuRepository $r */ $r = $this->getDoctrine()->getRepository(Menu::class); $menus = $r->getPaginatedList($page, $nbItemsPerPage, [], [], true); return $this->render('admin/menu/list.html.twig', [ 'menus' => $menus, 'pagination' => [ 'page' => $page, 'nbPages' => ceil($menus->count() / $nbItemsPerPage) ] ]); } /** * @Route("/create", name="admin.menu.create") * * @param Request $request * * @return Response */ public function create(Request $request): Response { return $this->edit(new Menu(), $request); } /** * @Route("/edit/{id}", name="admin.menu.edit") * * @param Menu $menu * @param Request $request * * @return Response */ public function edit(Menu $menu, Request $request): Response { // Use the MenuType from bundle $form = $this->createForm(MenuType::class, $menu); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($menu); $em->flush(); if ($form->get('save')->get('save')->isClicked()) { return $this->redirectToRoute('admin.menu.list'); } return $this->redirectToRoute('admin.menu.edit', ['id' => $menu->getId()]); } return $this->render('admin/menu/edit.html.twig', [ 'menu' => $menu, 'form' => $form->createView() ]); } /** * @Route("/delete/{id}", name="admin.menu.delete") * @Method({"GET", "DELETE"}) * * @param Menu $menu * @param Request $request * @return Response */ public function delete(Menu $menu, Request $request): Response { $form = $this->createFormBuilder() ->setMethod('DELETE') ->add('delete', SubmitType::class, [ 'attr' => [ 'class' => 'btn btn-danger' ] ]) ->getForm(); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->remove($menu); $em->flush(); return $this->redirectToRoute('admin.menu.list'); } return $this->render('admin/menu/delete.html.twig', [ 'menu' => $menu, 'form' => $form->createView() ]); } }
拖放部分
你必须将 CSS 和 JS 组件包含在你的 Webpack 管理入口点中
// ... require('../../vendor/lch/menu-bundle/Resources/public/css/lch_menu.css'); require('../../vendor/lch/menu-bundle/Resources/public/js/lch_menu'); //...
截图
菜单项组成
每个菜单项由一个标题、一个链接和一个名为 技术标签 的字段组成。最后一个用于携带你以后在展示中需要的任何上下文。此扩展包仅在菜单项上提供规范化阶段,具体展示则由模板根据你的需求创建。
注意:在上面的截图中,技术标签携带一个 SVG 图标名称。
菜单检索
要获取菜单数据,你必须使用 get_menu_items
Twig 扩展
{% for menuItem in get_menu_items('header', locale) %} <div class="c-header__pre__right__faq"> <a href="{{ menuItem.url }}"> {% if(menuItem.tags|length > 0) %} <svg class="icon-faq" viewBox="0 0 100 100"> <use xlink:href="#icon-{{ menuItem.tags[0] }}"></use> </svg> {% endif %} {{ menuItem.name }} </a> </div> {% endfor %}