rnr1721 / le7-menu-builder
le7 PHP MVC 框架或任何 PHP 8 项目的 HTML 菜单构建器
Requires
- php: >=8.1
- psr/simple-cache: ^3.0
- rnr1721/le7-links: ^1.0
Requires (Dev)
- phpunit/phpunit: ^10.0
- vimeo/psalm: ^5.7
README
le7 PHP MVC 框架或任何 PHP 8 项目的 HTML 菜单构建器
PHP 菜单管理器是一个灵活且可定制的类,允许您在 PHP 应用程序中创建、管理和渲染菜单。它提供添加、删除和修改菜单项的功能,以及以各种格式渲染菜单。
关键特性
- 创建和管理具有无限深度级别的层次结构菜单。
- 使用不同的渲染器在一个实例中管理多个不同的菜单。
- 管理菜单中链接的属性和 rel。
- 轻松添加、删除和修改菜单项。
- 通过提供自己的渲染引擎或使用默认引擎来自定义菜单渲染。
- 支持缓存以改善渲染菜单时的性能。
- 轻松从外部数据源导入和导出菜单项。
- 向链接 URL 添加 '变量',这些变量将被某些文本(模板)替换。
菜单管理器类旨在简单易用和扩展。它使用基于数组的结构来表示菜单,并提供操纵和渲染菜单的方法。
安装
composer require rnr1721/le7-menu-builder
测试
composer test
基本用法
use Core\MenuManager\MenuBuilder; use Core\MenuManager\Renderers\BootstrapMenuRenderer; // Create MenuBuilder instance $menuBuilder = new MenuBuilder(new BootstrapMenuRenderer()); // Add links to menu // key, label, url, parent_key, attributes, rels, weight $menuBuilder->addItem('home', 'Home', '/'); $menuBuilder->addItem('about', 'About', '/about'); // Here we add some class to menu link $menuBuilder->addItem('services', 'Services', '/services', null, ['class' => 'myclass']); // Here we add some rel to menu link $menuBuilder->addItem('products', 'Products', '/products', null, [], ['nofollow']); // Here we add weight for sorting $menuBuilder->addItem('solutions', 'Solutions', '/solutions', null, [], [], 30); // Add child links to existing menu items $menuBuilder->addItem('contact', 'Contact', '/contact', 'about'); $menuBuilder->addItem('support', 'Support', '/support', 'services'); // Add some attribute for existing link in menu // In this case we will add ID for link $menuBuilder->addAttribute('support','id','myclass'); // Add attribute "class" => 'active' to link by key $menuBuilder->makeActive('about'); // Remove link from menu by key $menuBuilder->removeLink('services'); // Render the menu $html = $menuBuilder->render(); // Optionally, you can render menu with some options or alternative renderer $html = $menuBuilder->render($options, $renderer); // Build raw menu array $menu = $menuBuilder->build();
在 MenuBuilder 的一个实例中创建多个不同的菜单
您可以在一个实例中构建和渲染不同的菜单。当您创建 MenuBuilder 的实例时,它将创建默认菜单 'default'。但您也可以轻松创建另一个并使其生效。示例
use Core\MenuManager\MenuBuilder; use Core\MenuManager\Renderers\BootstrapMenuRenderer; // Create MenuBuilder instance $menuBuilder = new MenuBuilder(new BootstrapMenuRenderer()); // Add item to default menu $menuBuilder->addItem('home', 'Home', '/'); // Create and set active another menu $menuBuilder->setActiveMenu('newMenu'); // Add item to default menu or make some else $menuBuilder->addItem('about', 'About', '/about'); // Switch to default menu $menuBuilder->setActiveMenu('default'); // Render first menu (with Home item) $menuBuilder->render();
链接中的 '变量'(模板化链接)
在某些情况下,您可能需要在链接中存储变量,而不是完整的 URL。
use Core\Links\Link; use Core\MenuManager\MenuBuilder; use Core\MenuManager\Renderers\BootstrapMenuRenderer; // Create MenuBuilder instance $menuBuilder = new MenuBuilder(new BootstrapMenuRenderer()); $menuBuilder->setUrlReplaceVars('url','https://example.com'); // Add item to menu $menuBuilder->addItem('about', 'About', '{url}/about');
现在,如果您导出您的菜单,{url} 将被替换为 https://example.com 重要:它不会与使用 addRawItem 方法添加的原始链接一起工作。
原始链接
该项目使用此 PSR LinkInterface 的实现:https://github.com/rnr1721/le7-links 此实现同时包含 PSR LinkInterface 和 UriInterface,但包含自己的方法,如 render、getAnchor、withAnchor 等...
use Core\Links\Link; use Core\MenuManager\MenuBuilder; use Core\MenuManager\Renderers\BootstrapMenuRenderer; // Create MenuBuilder instance $menuBuilder = new MenuBuilder(new BootstrapMenuRenderer()); // Here we create link with rel="nofollow" and class="myClass" and anchor "About" $link = new Link( 'https://example.com/about', ['nofollow'], ['class'=>'myClass'], 'About' ); // Parameters - key, link object, parentKey, weight $menuBuilder->addRawItem('about', $link, null 80); // Render the menu $menuBuilder->render();
渲染器选项
任何 MenuRenderer 都有一组自己的设置作为数组。您可以看到默认设置并在渲染时更改它们。例如,对于 bootstrap 渲染器
use Core\Links\Link; use Core\MenuManager\MenuBuilder; use Core\MenuManager\Renderers\BootstrapMenuRenderer; // Create MenuBuilder instance $menuBuilder = new MenuBuilder(new BootstrapMenuRenderer()); // Get array of default renderer options $options = $menuBuilder->getRendererOptions();
当然,您可以更改这些选项
use Core\Links\Link; use Core\MenuManager\MenuBuilder; use Core\MenuManager\Renderers\BootstrapMenuRenderer; // Create MenuBuilder instance $menuBuilder = new MenuBuilder(new BootstrapMenuRenderer()); // Add menu items $menuBuilder->addItem('home', 'Home', '/'); $menuBuilder->addItem('about', 'About', '/about'); $options = [ 'menuId' => 'default', 'navClass' => 'navbar navbar-expand-lg navbar-light bg-light', 'containerClass' => 'container', 'wrapperClass' => 'collapse navbar-collapse', 'menuClass' => 'navbar-nav', 'menuItemClass' => 'nav-item', 'menuAttributes' => [], 'menuItemAttributes' => ['class' => 'nav-link'], 'subMenuClass' => 'dropdown-menu', 'subMenuStyle' => '', 'openOnHover' => false, 'animationSpeed' => 'fast', 'whiteSpaces' => 4 ]; // Render with options $menuBuilder->render($options);
重要:不需要设置所有选项,您可以仅更改需要更改的选项。此外,您不能更改选项的数据类型,这将引发异常。每个渲染器都可以有自己的选项列表或没有。
缓存选项
您可以将菜单渲染结果缓存起来。
use Psr\SimpleCache\CacheInterface; // Create an instance of MenuBuilder with cache support $renderer = /* get an instance of a class implementing the MenuRendererInterface */; $cache = /* get an instance of a class implementing the CacheInterface */; $menuBuilder = new MenuBuilder($renderer, $cache); // Set cache TTL (Time To Live) $cacheTtl = 3600; // cache TTL in seconds can be null|int|DateInterval $menuBuilder->setCacheTtl($cacheTtl); // Set cache prefix (default is menu_) $menuBuilder->setCacheKeyPrefix('menu_en_'); // Generate the menu and cache its result $menuHtml = $menuBuilder->render();
渲染器
现在有这些渲染器可用,但您可以编写自己的渲染器,该渲染器实现了 MenuRendererInterface。现在,开箱即用的渲染器有这些
- BootstrapMenuRenderer 与 HtmlMenuRenderer 相同,但针对 bootstrap 特定
- HtmlMenuRenderer 渲染 HTML 菜单
- ArrayMenuRenderer 渲染数组菜单
- JsonMenuRenderer 渲染 JSON 菜单
MenuRendererInterface
<?php declare (strict_types=1); namespace Core\Interfaces; interface MenuRendererInterface { public function render( array $menu = [], ?array $options = null ): mixed; public function getOptions(): array; }
您可以通过提供自己的渲染引擎或修改默认引擎来自定义菜单的渲染。此外,启用缓存可以改善渲染菜单时的性能。
导入和导出菜单项配置
您可以导入和导出菜单项配置。
示例
use Core\MenuManager\MenuBuilder; use Core\MenuManager\Renderers\HtmlMenuRenderer; // Create MenuBuilder instance $menuBuilder = new MenuBuilder(new HtmlMenuRenderer()); $items = [ 'admin' => [ [ 'key' => 'home', 'label' => 'Home', 'url' => 'http://example.com', 'parentKey' => null, 'rels' => [], 'attributes' => [], 'weight' => 50 ], [ 'key' => 'about', 'label' => 'About', 'url' => 'http://example.com/about', 'parentKey' => null, 'rels' => [], 'attributes' => [], 'weight' => 50 ] ] ]; // Import menu items configuration from array $menuBuilder->importSource($items); // Export menu items configuration to array $menuBuilder->exportSource();
使用示例的另一个例子
use Core\MenuManager\MenuBuilder; use Core\MenuManager\Renderers\HtmlMenuRenderer; // Create MenuBuilder instance $menuBuilder = new MenuBuilder(new HtmlMenuRenderer()); // Add links to menu $menuBuilder->addItem('home', 'Home', '/'); $menuBuilder->addItem('about', 'About', '/about'); $menuBuilder->addItem('services', 'Services', '/services', null, ['class' => 'myclass']); $menuBuilder->addItem('products', 'Products', '/products', null, [], ['nofollow']); $menuBuilder->addItem('solutions', 'Solutions', '/solutions', null, [], [], 30); // Add child links to existing menu items $menuBuilder->addItem('contact', 'Contact', '/contact', 'about'); $menuBuilder->addItem('support', 'Support', '/support', 'services'); // Add some attribute for an existing link in the menu $menuBuilder->addAttribute('support', 'id', 'myclass'); // Add attribute "class" => 'active' to a link by key $menuBuilder->makeActive('about'); // Remove a link from the menu by key $menuBuilder->removeLink('services'); // Render the menu $html = $menuBuilder->render(); // Get the options for the renderer $options = $menuBuilder->getRendererOptions(); // Customize the rendering options $options['menuClass'] = 'my-menu'; $options['menuItemClass'] = 'my-menu-item'; // Render the menu with the customized options $html = $menuBuilder->render($options);