轻松管理菜单。

3.0.5 2020-06-24 12:46 UTC

README

Build Status Total Downloads Latest Stable Version Latest Unstable Version License

API 文档

你是那种喜欢在视图文件中手动编写菜单的人吗?或者你发现自己在寻找保存网站页面链接的最佳位置?那么,菜单(Menu)就是为你准备的!

快速概览示例

$menu = Menu::handler('mailbox'); 

// items
$menu
    ->add('contacts', 'Contacts')
    ->add('inbox', 'Inbox')
    ->raw(null, null, ['class' => 'divider'])
    ->add('folders', 'Folders', Menu::items() 
        ->prefixParents() 
        ->add('urgent', 'Urgent') // with prefix: /folders/urgent
        ->add('sent', 'Sent')
        ->add('deleted', 'Deleted')
    );

// styling
$menu
    ->addClass('nav navbar-nav')
    ->getItemsByContentType(Menu\Items\Contents\Link::class)
    ->map(function($item) {
        if ( $item->isActive() )  {
            $item->addClass('active');
        }
    });

{!! $menu !!} 将输出

<ul class="nav navbar-nav">
  <li class="active"> <!-- current element in laravel, detected by library -->
    <a href="http://myapp.com/contacts">Contacts</a>
  </li>
  <li>
    <a href="http://myapp.com/inbox">Inbox</a>
  </li>
  <li class="divider"></li>
  <li>
    <a href="http://myapp.com/folders">Folders</a>
    <ul>
      <li>
        <a href="http://myapp.com/folders/urgent">Urgent</a>
      </li>
      <li>
        <a href="http://myapp.com/folders/sent">Sent</a>
      </li>
      <li>
        <a href="http://myapp.com/folders/deleted">Deleted</a>
      </li>
    </ul>
  </li>
</ul>

关键概念

项目列表

项目列表是菜单的核心,它应该很容易理解,因为它仅仅存储了一个项目列表。项目列表有一些可用的配置。例如,你可以设置用于渲染列表的 HTML 元素,在每个项目中添加所有父级 URL 段落作为前缀,等等。我们将在后面探讨这些选项。

菜单处理器

菜单处理器允许我们创建和交互项目列表,并且是存储和检索我们的菜单的地方。因为我们能够同时交互多个项目列表,所以我们有了一些有趣的选项。

项目

Menu 包箱提供了两种类型的项目。

  • 链接 用于创建到其他页面的链接
  • 原始 你可以在项目中添加任何你喜欢的。这种类型通常用于分隔符、标题等。

项目的 HTML 元素和属性也可以更改,我们将在后面讨论这个话题。

安装

Laravel 3

通过 artisan 命令行工具安装 Menu。打开终端,导航到你的 Laravel 项目的根目录。现在输入以下命令

php artisan bundle:install menu

为了让 Laravel 知道 Laravel Menu 包应该启动,打开 application/packages.php 并将以下行添加到 packages 数组中。

'menu' => array('auto' => true),

Laravel 4

将以下内容添加到你的 composer.json 文件中的 "require"

"vespakoen/menu": "2.*"

并将以下内容添加到你的 app/config/app.php 文件中

  • 在 Service Providers 数组中: 'Menu\MenuServiceProvider',
  • 在 aliases 数组中: 'Menu' => 'Menu\Menu',

Laravel 5

将以下内容添加到你的 composer.json 文件中的 "require"

"vespakoen/menu": "3.*"

将以下内容添加到你的 config/app.php 文件中

  • 在 Service Providers 数组中: 'Menu\MenuServiceProvider',
  • 在 aliases 数组中: 'Menu' => 'Menu\Menu',

最后,从你的项目根目录运行以下命令

php artisan vendor:publish

基本用法

首先,让我们将一些页面加载到菜单中。我们将通过利用 hydrate 方法来完成此操作。

Menu::handler('main')->hydrate(function()
  {
    return Page::with('translation')
      ->where('group', '=', 'main')
      ->get();
  },
  function($children, $item)
  {
    $children->add($item->translation->slug, $item->translation->name, Menu::items($item->as));
  });

/* the hydrate method takes these arguments
  $resolver       Closure     A callback to resolve results
  $decorator      Closure     A callback that gets called for every result fetched from the resolver with the corresponding ItemList and result as the arguments
  $idField        integer (default = 'id')           the property on the result that contains the id
  $parentIdField  integer (default = 'parent_id')    the property on the result that contains the parent id
  $parentId       integer (default = 0)              the parentId to start hydrating from
*/

现在我们已经将页面加载到菜单中,甚至通过 Menu::items($item->as) 为每个菜单项识别了名称,我们有很多选项可供选择。

通过名称查找节点并添加子项。

Menu::find('users')
  ->add('users/create', 'Create new user');

为根节点添加一些属性

Menu::handler('main')
  ->addClass('nav navbar-nav');

获取一定深度处的所有 ItemList 并添加一个类

Menu::handler('main')
  ->getItemListsAtDepth(0)
  ->addClass('level-1');

获取深度范围的所有 ItemList 并更改元素

Menu::handler('main')
  ->getItemListsAtDepthRange(0,2)
  ->setElement('div');

获取一定深度处的所有 Item 并添加一个类

Menu::handler('main')
  ->getItemsAtDepth(0)
  ->addClass('level-1');

通过内容类型获取 Item 并使用 map 函数遍历结果,根据收集到的信息执行操作

Menu::handler('main')
  ->getItemsByContentType('Menu\Items\Contents\Link')
  ->map(function($item)
  {
    if($item->isActive() && $item->hasChildren())
    {
      $item->addClass('is-active-link-with-children');
    }

    if($item->getContent()->getUrl() == 'home')
    {
      $item->addClass('is-home');
    }
  });

获取所有 ItemList 并如果它们有子项则添加一个类

Menu::handler('main')
  ->getAllItemLists()
  ->map(function($itemList)
  {
    if($itemList->hasChildren())
    {
      $itemList->addClass('has-children');
    }
  });

面包屑

面包屑地狱已成为过去。

准备好的 Bootstrap 面包屑就像这样简单

Menu::handler('main')
    ->breadcrumbs()
    ->setElement('ol')
    ->addClass('breadcrumb');

面包屑方法搜索所有处理程序并返回一个普通的ItemList,你可以对其进行操作。如果你直接在Menu类上调用面包屑方法,它将搜索所有你的处理程序中的面包屑,并且默认返回第一个匹配项。但是,可能有些情况下你想从找到的面包屑中选择,为此你可以将回调方法作为第一个参数提供。

以下是一个示例:

Menu::breadcrumbs(function($itemLists)
    {
      return $itemLists[0]; // returns first match
    })
    ->setElement('ol')
    ->addClass('breadcrumb');

深入了解

Laravel Menu包包含几个类,但你可以通过Menu类与它们全部交互。让我们来看看handler方法。它只接受一个字符串或数组作为参数,给定的字符串是我们要检索的项目列表的名称。如果请求的项目列表还不存在,它将为我们创建它。在菜单类找到并创建了我们要的项目列表之后,它将返回一个处理这些项目列表的菜单处理程序。

// Get a MenuHandler instance that handles an ItemList named "main"
Menu::handler('main');

当我们对这个菜单处理程序调用一个方法时,它将简单地转发调用到它所管理的所有项目列表。为了了解我们现在有了处理程序可以做什么,我们需要看看ItemList类上的方法。

ItemList类有一个名为add的方法,你可能经常使用它。它向ItemList添加一个类型为"link"的Item

Menu::handler('main')->add('home', 'Homepage');

/* The add method takes these arguments
  $url  string  The URL to another page
  $title  string  The visible string on the link
  $children (default = null)  ItemList  (optional) The children of this page
  $link_attributes (default = array())  array (optional) HTML attributes for the <a> element
  $item_attributes (default = array())  array (optional) HTML attributes for the list element (usually <li>)
  $item_element (default = 'li')  string  (optional) The type of the list element
*/

让我们看看raw方法,用于向列表添加"任何内容"。

Menu::handler('main')->raw('<img src="img/seperator.gif">');

/* The raw method takes these arguments
  $html string  The contents of the item
  $children (default = null)  ItemList  (optional) The children of this item
  $item_attributes (default = array())  array (optional) HTML attributes for the list element (usually <li>)
  $item_element (default = 'li')  string  (optional) The type of the list element
*/

太好了!现在我们知道了如何向项目列表添加项目,让我们看看如何向项目添加子项。每个项目都可以有子项,子项对象是另一个ItemList。正如我们之前看到的,我们可以通过handler方法创建项目列表,但这个方法返回一个MenuHandler,使其无法用于项目子项。那么我们该用什么呢?items方法返回一个新的ItemList对象。让我们看看。

Menu::handler('main')
    ->add('home', 'Homepage', Menu::items()
        ->add('sub-of-home', 'Sub of homepage'));

/* The items method takes these arguments
  $name (default = null)  string  (optional) The name (=identifier) of this ItemList
  $attributes (default = array()) array (optional) HTML attributes for the ItemList element (usually <ul>)
  $element (default = 'ul') string  (optional) The type of the ItemList element
*/

因此,现在我们知道如何构建菜单,添加项目和带有子项的项目。让我们看看如何显示菜单。MenuHandler和ItemList类实现了"__toString"方法,该方法调用render方法。这意味着你可以简单地echo MenuHandler或ItemList对象。以下是一个示例,以使事情更加清晰。

echo Menu::handler('main');

// Is the same as

echo Menu::handler('main')->render();

现在我们已经掌握了基础知识,我们将探索这个包提供的其他一些酷炫特性。

类图

Class diagram

一些最后的话

感谢您跟随使用这个包。特别感谢@Anahkiasen重构了这个包并给它注入了新的活力!