gaba93/laravel-menu-updated

Laravel 5.5 菜单生成器

1.3 2017-07-31 18:27 UTC

This package is not auto-updated.

Last update: 2024-09-23 06:21:48 UTC


README

Latest Stable Version Latest Unstable Version Total Downloads License

在 Laravel 5 中快速创建菜单的简单方法

对于 Laravel 4.x,请查看 版本 1.5.0

文档

安装

composer require lavary/laravel-menu

现在,将 Laravel Menu 服务提供者添加到 config/app.php 中的 providers 数组。

<?php

'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Foundation\Providers\ArtisanServiceProvider::class,
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
	
	...
        
        'Lavary\Menu\ServiceProvider',
        
        ...

],
?>

config/app.php 的末尾添加 'Menu' => 'Lavary\Menu\Facade'$aliases 数组

<?php

'aliases' => [

    'App'       => Illuminate\Support\Facades\App::class,
    'Artisan'   => Illuminate\Support\Facades\Artisan::class,
    ...
    'Menu'       => 'Lavary\Menu\Facade',

],
?>

这将注册包到 Laravel 并创建一个名为 Menu 的别名。

入门

您可以在 laravel 中间件 中定义菜单定义。因此,每次请求击中您的应用程序时,菜单对象都将可用于所有视图。

以下是基本用法

<?php
Menu::make('MyNavBar', function($menu){
  
  $menu->add('Home');
  $menu->add('About',    'about');
  $menu->add('services', 'services');
  $menu->add('Contact',  'contact');
  
});
?>

注意 $MyNavBar 是我在这些示例中使用的假设名称;您可以为您的菜单命名任何您想要的。

在上面的示例中,Menu::make() 创建了一个名为 MyNavBar 的菜单,将菜单实例添加到 Menu::collection,并最终使 $myNavBar 对象在所有应用视图中可用。

此方法接受一个可调用的函数,您可以在其中定义菜单项。add 方法定义一个新项。它接收两个参数,第一个是项标题,第二个是选项。

选项 可以是一个表示 URL 的简单字符串或一个关联数组,我们将很快讨论。

在视图中渲染菜单

Laravel-menu 默认提供三种渲染方法。但是,您可以使用正确的方法和属性创建自己的渲染方法。

如前所述,laravel-menu 默认提供三种渲染格式,asUl()asOl()asDiv()。您可以在此处阅读有关详细信息的内容

{!! $MyNavBar->asUl() !!}

您还可以通过菜单集合访问菜单对象

{!! Menu::get('MyNavBar')->asUl() !!}

这将按如下方式渲染您的菜单

<ul>
  <li><a href="http://yourdomain.com">Home</a></li>
  <li><a href="http://yourdomain.com/about">About</a></li>
  <li><a href="http://yourdomain.com/services">Services</a></li>
  <li><a href="http://yourdomain.com/contact">Contact</a></li>
</ul>

这就是全部内容!

路由

URL

您可以通过将 URL 作为 add 方法的第二个参数传递来简单地分配一个 URL 给您的菜单项

<?php
// ...
$menu->add('About Us', 'about-us');
// ...

命名路由

laravel-menu 也支持命名路由

这次我们不是将简单字符串传递给 add(),而是传递一个包含键 route 和命名路由值的关联数组

<?php

// Suppose we have these routes defined in our app/routes.php file 

//...
Route::get('/',        array('as' => 'home.page',  function(){...}));
Route::get('about',    array('as' => 'page.about', function(){...}));
//...

// Now we make the menu:

Menu::make('MyNavBar', function($menu){
  
  $menu->add('Home',     array('route'  => 'home.page'));
  $menu->add('About',    array('route'  => 'page.about'));
  // ...

});
?>

控制器操作

Laravel菜单支持控制器动作。

您只需将选项数组的action键设置为控制器动作。

<?php

// Suppose we have these routes defined in our app/Http/routes.php file

// ...
Route::get('services', 'ServiceController@index');
//...


  // ...
  $menu->add('services', array('action' => 'ServicesController@index'));
  // ...

?>

注意:如果您需要将一些数据作为查询字符串发送到路由、URL或控制器动作,您只需将它们包含在一个数组中,并带有路由、动作或URL值。

<?php
Menu::make('MyNavBar', function($menu){
  
  $menu->add('Home',     array('route'  => 'home.page'));
  $menu->add('About',    array('route'  => array('page.about', 'template' => 1)));
  $menu->add('services', array('action' => array('ServicesController@index', 'id' => 12)));
 
  $menu->add('Contact',  'contact');

});
?>

HTTPS

如果您需要通过HTTPS提供路由,请在项目的link属性上调用secure(),或者将选项数组中的secure键添加并设置为true

<?php
	// ...
	$menu->add('Members', 'members')->link->secure();
	
	
	// or alternatively use the following method
	
	$menu->add('Members', array('url' => 'members', 'secure' => true));
	
	// ...

?>

输出为<ul>将如下所示:

<ul>
	...
	<li><a href="https://yourdomain.com/members">Members</a></li>
	...
</ul>

子项

项目也可以有子项目。

<?php
Menu::make('MyNavBar', function($menu){

  //...
  
  $menu->add('About',    array('route'  => 'page.about'));
  
  // these items will go under Item 'About'
  
  // refer to about as a property of $menu object then call `add()` on it
  $menu->about->add('Who We are', 'who-we-are');

  // or
  
  $menu->get('about')->add('What We Do', 'what-we-do');
  
  // or
  
  $menu->item('about')->add('Our Goals', 'our-goals');
  
  //...

});
?>

您也可以链式调用项目定义,并深入到您希望的深度。

<?php

  // ...
  
  $menu->add('About',    array('route'  => 'page.about'))
		     ->add('Level2', 'link address')
		          ->add('level3', 'Link address')
		               ->add('level4', 'Link address');
        
  // ...      
?>

您可以使用parent属性直接添加子项目。

<?php
	//...
	$menu->add('About',    array('route'  => 'page.about'));
	$menu->add('Level2', array('url' => 'Link address', 'parent' => $menu->about->id));
	//...
?>

手动设置项目ID。

当您添加新项目时,会自动为项目分配一个唯一的ID。然而,在从数据库加载菜单项并需要手动设置ID的情况下,您可以调用项目对象的id()方法并传递您想要的ID来处理这种情况。

<?php
	// ...
	$menu->add('About', array('route' => 'page.about'))
	     ->id('74398247329487')
	// ...

或者,您可以在添加菜单项时,将ID作为选项数组的元素传递。

<?php
	// ...
	$menu->add('About', array('route' => 'page.about', 'id' => 74398247329487));
	// ...

手动设置项目昵称。

当您添加新项目时,会自动为项目分配一个昵称以供进一步引用。这个昵称是项目标题的驼峰形式。例如,标题为About Us的项目将具有昵称aboutUs。但是,有时您可能需要显式定义您的菜单项,因为您使用的是特殊的字符集。为此,您可以使用项目对象的nickname()方法,并将您想要的昵称传递给它。

<?php
	// ...
	$menu->add('About', array('route' => 'page.about'))
	     ->nickname('about_menu_nickname');
	     
	// And use it like you normally would
	$menu->item('about_menu_nickname');     
	     
	// ...

或者,您可以将昵称作为选项数组的元素传递。

<?php
	// ...
	$menu->add('About', array('route' => 'page.about', 'nickname' => 'about_menu_nickname'));
	
	// And use it like you normally would
	$menu->item('about_menu_nickname');    
	// ...

引用项

您可以使用以下方法在代码中访问定义的项目。

通过标题获取项

包括项目的标题在驼峰形式中。

<?php
	// ...
	
	$menu->itemTitleInCamelCase ...
	
	// or
	
	$menu->get('itemTitleInCamelCase') ...
	
	// or
	
	$menu->item('itemTitleInCamelCase') ...
	
	// ...
?>

例如,让我们在我们定义了About us项目之后在其后插入一个分隔符。

<?php
    // ...
	
	$menu->add('About us', 'about-us')
	
	$menu->aboutUs->divide();
	
	// or
	
	$menu->get('aboutUs')->divide();
	
	// or
	
	$menu->item('aboutUs')->divide();
	
	// ...
?>

如果您不熟悉上述方法,可以将项目对象的引用存储在变量中,以供进一步引用。

<?php
// ...
$about = $menu->add('About', 'about');
$about->add('Who We Are', 'who-we-are');
$about->add('What We Do', 'what-we-do');
// ...

通过ID获取项目。

如果需要,您也可以通过ID获取项目。

<?php
	// ...
	$menu->find(12) ...
	// ...
?>

获取所有项

<?php
	// ...
	$menu->all();

	// or outside of the builder context
	Menu::get('MyNavBar')->all();
	// ...
?>

all()返回一个Laravel Collection

获取第一个项

<?php
	// ...
	$menu->first();

	// or outside of the builder context
	Menu::get('MyNavBar')->first();
	// ...
?>

获取最后一个项

<?php
	// ...
	$menu->last();

	// or outside of the builder context
	Menu::get('MyNavBar')->last();
	// ...
?>

获取项目的子项目。

首先,您需要使用上述方法获取项目,然后在上面调用children()

要获取About项目的子项目:

<?php
	// ...
	$aboutSubs = $menu->about->children();

	// or outside of the builder context
	$aboutSubs = Menu::get('MyNavBar')->about->children();

	// Or
	$aboutSubs = Menu::get('MyNavBar')->item('about')->children();
	// ...
?>

children()返回一个Laravel Collection

要检查一个项目是否有子项目,您可以使用hasChildren()

<?php
	// ...
	if( $menu->about->hasChildren() ) {
		// Do something
	}

	// or outside of the builder context
	Menu::get('MyNavBar')->about->hasChildren();

	// Or
	Menu::get('MyNavBar')->item('about')->hasChildren();
	// ...
?>

要获取项目的所有后代,您可以使用all

<?php
// ...
$aboutSubs = $menu->about->all();
// ...

魔法 Where 方法

您还可以使用魔术where方法搜索项目集合。这些方法由一个where加上一个属性(对象属性或元数据)组成。

例如,要获取父项等于12的项目,您可以这样做:

<?php
	// ...
	$subs = $menu->whereParent(12);
	// ...
?>

或者要获取具有特定元数据的项目:

<?php
	// ...
	$menu->add('Home',     '#')->data('color', 'red');
	$menu->add('About',    '#')->data('color', 'blue');
	$menu->add('Services', '#')->data('color', 'red');
	$menu->add('Contact',  '#')->data('color', 'green');
	// ...
	
	// Fetch all the items with color set to red:
	$reds = $menu->whereColor('red');
	
?>

此方法返回一个Laravel collection

如果您需要获取匹配项的后代,只需将第二个参数设置为true。

<?php
$reds = $menu->whereColor('red', true);

这将给出所有颜色为红色及其后代的项。

引用菜单实例。

您可能会遇到需要在不处于构建器上下文的情况下引用菜单实例的情况。

要按名称获取特定菜单:

<?php
	// ...
	$menu = Menu::get('MyNavBar');
	// ...
?>

或获取所有菜单实例:

<?php
	// ...
	$menus = Menu::all();
	// ...
?>

您还可以调用getCollection()来获取相同的结果。

<?php
	// ...
	$menus = Menu::getCollection();
	// ...
?>

两种方法都返回一个Laravel Collection

HTML 属性

由于所有菜单项都将渲染为HTML实体,如列表项或div,因此您可以为每个项目定义所需的HTML属性数量。

<?php
Menu::make('MyNavBar', function($menu){

  // As you see, you need to pass the second parameter as an associative array:
  $menu->add('Home',     array('route'  => 'home.page',  'class' => 'navbar navbar-home', 'id' => 'home'));
  $menu->add('About',    array('route'  => 'page.about', 'class' => 'navbar navbar-about dropdown'));
  $menu->add('services', array('action' => 'ServicesController@index'));
  $menu->add('Contact',  'contact');

});
?>

如果我们选择HTML列表作为我们的渲染格式,如ul,结果将类似于以下内容:

<ul>
  <li class="navbar navbar-home" id="home"><a href="http://yourdomain.com">Home</a></li>
  <li class="navbar navbar-about dropdown"><a href="http://yourdomain.com/about">About</a></li>
  <li><a href="http://yourdomain.com/services">Services</a></li>
  <li><a href="http://yourdomain.com/contact">Contact</a></li>
</ul>

您还可以使用attr()方法在定义项目之后设置或获取HTML属性。

如果您使用一个参数调用 attr(),它将为您返回属性值。如果您使用两个参数调用它,它将考虑第一个和第二个参数作为一个键/值对来设置属性。如果您需要一次性添加一组HTML属性,也可以传递一个关联数组;最后,如果您不带任何参数调用它,它将返回一个包含所有属性的数组。

<?php
	//...
	$menu->add('About', array('url' => 'about', 'class' => 'about-item'));
	
	echo $menu->about->attr('class');  // output:  about-item
	
	$menu->about->attr('class', 'another-class');
	echo $menu->about->attr('class');  // output:  about-item another-class

	$menu->about->attr(array('class' => 'yet-another', 'id' => 'about')); 
	
	echo $menu->about->attr('class');  // output:  about-item another-class yet-another
	echo $menu->about->attr('id');  // output:  id
	
	print_r($menu->about->attr());
	
	/* Output
	Array
	(
		[class] => about-item another-class yet-another
		[id] => id
	)
	*/
	
	//...
?>

如果您需要针对一组项目,可以使用 attr 在一个集合上。

<?php
  // ...
  $menu->add('About', 'about');
  
  $menu->about->add('Who we are', 'about/whoweare');
  $menu->about->add('What we do', 'about/whatwedo');
  
  // add a class to children of About
  $menu->about->children()->attr('class', 'about-item');
  
  // ...

操作链接

所有HTML属性都会应用到包装标签(如li、div等);您可能会遇到需要向 <a> 标签添加一些HTML属性的情况。

每个 Item 实例都有一个属性,用于存储 Link 对象的实例。此对象为您提供用于操作 <a> 标签的能力。

和每个项目一样,Link 也具有一个与项目相同的 attr() 方法。

<?php
Menu::make('MyNavBar', function($menu){

 //  ...
  
  $about = $menu->add('About',    array('route'  => 'page.about', 'class' => 'navbar navbar-about dropdown'));
  
  $about->link->attr(array('class' => 'dropdown-toggle', 'data-toggle' => 'dropdown'));
  
 // ...
  
});
?>

链接的 Href 属性

如果您不想使用 laravel-menu 的路由功能,或者不想构建器在URL前添加任何前缀(例如,您的主机地址),您可以显式设置您的链接的href属性。

<?php
// ...
$menu->add('About')->link->href('#');
// ...
?>

活动项

您可以使用 active() 在该项上标记一个项为激活状态。

<?php
	// ...
	$menu->add('Home', '#')->active();
	// ...
	
	/* Output
	
	<li class="active"><a href="#">#</a></li>	
	
	*/
	
?>

您也可以将 active 类添加到锚点元素,而不是包装元素(如divli)。

<?php
	// ...
	$menu->add('Home', '#')->link->active();
	// ...
	
	/* Output
	
	<li><a class="active" href="#">#</a></li>	
	
	*/
	
?>

Laravel Menu 会根据您注册项时的时间自动根据当前 URI 做这件事。

您还可以在位于包配置目录的 settings.php 文件中的 settings.php 中选择要激活的元素(项目或链接)。

	// ...
	'active_element' => 'item',    // item|link
	// ...

RESTful URL

只要在 config/settings.php 文件中将 restful 选项设置为 true,就支持RESTful URL。例如,具有URL resource 的菜单项将通过 resource/slugresource/slug/edit 激活。

您可能会遇到您的应用程序位于子目录而不是根目录,或者您的资源有一个公共前缀的情况;在这种情况下,您需要将 rest_base 选项设置为适当的子前缀以获得更好的RESTful激活支持。rest_base 可以接受一个简单的字符串、字符串数组或函数调用的值。

URL 通配符

laravel-menu 允许您为某些项目定义一个模式,如果自动激活无法帮助的话。

<?php
// ...
$menu->add('Articles', 'articles')->active('this-is-another-url/*');
// ...

因此,this-is-another-urlthis-is-another-url/and-another 都将激活 Articles 项目。

插入分隔符

您可以使用 divide() 方法在每个项目后插入一个分隔符。

<?php
	//...
	$menu->add('Separated Item', 'item-url')->divide()
	
	// You can also use it this way:
	
	$menu->('Another Separated Item', 'another-item-url');
	
	// This line will insert a divider after the last defined item
	$menu->divide()
	
	//...
	
	/*
	Output as <ul>:
	
		<ul>
			...
			<li><a href="item-url">Separated Item</a></li>
			<li class="divider"></li>
			
			<li><a href="another-item-url">Another Separated Item</a></li>
			<li class="divider"></li>
			...
		</ul>
		
	*/

?>

divide() 也可以接受一个关联数组作为属性。

<?php
	//...
	$menu->add('Separated Item', 'item-url')->divide( array('class' => 'my-divider') );
	//...
	
	/*
	Output as <ul>:
	
		<ul>
			...
			<li><a href="item-url">Separated Item</a></li>
			<li class="my-divider divider"></li>
		
			...
		</ul>
		
	*/
?>

追加和前置

您可以在定义项目标题后使用 prependappend 将HTML或纯文本添加到每个项目的标题。

<?php
Menu::make('MyNavBar', function($menu){

  // ...
  
  $about = $menu->add('About',    array('route'  => 'page.about', 'class' => 'navbar navbar-about dropdown'));
  
  $menu->about->attr(array('class' => 'dropdown-toggle', 'data-toggle' => 'dropdown'))
              ->append(' <b class="caret"></b>')
              ->prepend('<span class="glyphicon glyphicon-user"></span> ');
              
  // ...            

});
?>

上面的代码将得到以下结果

<ul>
  ...
  
  <li class="navbar navbar-about dropdown">
   <a href="about" class="dropdown-toggle" data-toggle="dropdown">
     <span class="glyphicon glyphicon-user"></span> About <b class="caret"></b>
   </a>
  </li>
</ul>

您也可以在集合上调用 prependappend

原始项

要插入作为纯文本而不是超链接的项目,您可以使用 raw()

<?php
    // ...
    $menu->raw('Item Title', array('class' => 'some-class'));  
    
    $menu->add('About', 'about');
    $menu->About->raw('Another Plain Text Item')
    // ...
    
    /* Output as an unordered list:
       <ul>
            ...
            <li class="some-class">Item's Title</li>
            <li>
                About
                <ul>
                    <li>Another Plain Text Item</li>
                </ul>
            </li>
            ...
        </ul>
    */
?>

菜单组

有时您可能需要在多个项之间共享属性。而不是为每个项指定属性和选项,您可以使用菜单组功能。

PS:此功能与 Laravel 组路由的工作方式完全相同。

<?php
Menu::make('MyNavBar', function($menu){

  $menu->add('Home',     array('route'  => 'home.page', 'class' => 'navbar navbar-home', 'id' => 'home'));
  
  $menu->group(array('style' => 'padding: 0', 'data-role' => 'navigation') function($m){
    
        $m->add('About',    array('route'  => 'page.about', 'class' => 'navbar navbar-about dropdown'));
        $m->add('services', array('action' => 'ServicesController@index'));
  }
  
  $menu->add('Contact',  'contact');

});
?>

属性 styledata-role 将应用于 AboutServices 项目。

<ul>
    <li class="navbar navbar-home" id="home"><a href="http://yourdomain.com">Home</a></li>
    <li style="padding: 0" data-role="navigation" class="navbar navbar-about dropdown"><a href="http://yourdomain.com/about"About</a></li>
    <li style="padding: 0" data-role="navigation"><a href="http://yourdomain.com/services">Services</a></li>
</ul>

URL 前缀

就像 Laravel 路由前缀功能一样,可以使用传递给组的数组中的 prefix 选项为菜单项组添加前缀。

注意:前缀仅适用于使用 url 标记的菜单项,但不适用于 routeaction

<?php
Menu::make('MyNavBar', function($menu){

  $menu->add('Home',     array('route'  => 'home.page', 'class' => 'navbar navbar-home', 'id' => 'home'));
  
  $menu->add('About', array('url'  => 'about', 'class' => 'navbar navbar-about dropdown'));  // URL: /about 
  
  $menu->group(array('prefix' => 'about'), function($m){
  
  	$about->add('Who we are?', 'who-we-are');   // URL: about/who-we-are
  	$about->add('What we do?', 'what-we-do');   // URL: about/what-we-do
  	
  });
  
  $menu->add('Contact',  'contact');

});
?>

这将生成以下内容

<ul>
    <li  class="navbar navbar-home" id="home"><a href="/">Home</a></li>
    
    <li  data-role="navigation" class="navbar navbar-about dropdown"><a href="http://yourdomain.com/about/summary"About</a>
    	<ul>
    	   <li><a href="http://yourdomain.com/about/who-we-are">Who we are?</a></li>
    	   <li><a href="http://yourdomain.com/about/who-we-are">What we do?</a></li>
    	</ul>
    </li>
    
    <li><a href="services">Services</a></li>
    <li><a href="contact">Contact</a></li>
</ul>

嵌套组

Laravel Menu 也支持嵌套分组功能。一个菜单组将其自己的属性与其父组合并,然后与其包装的项目共享这些属性。

<?php
Menu::make('MyNavBar', function($menu){

	// ...
	
	$menu->group(array('prefix' => 'pages', 'data-info' => 'test'), function($m){
		
		$m->add('About', 'about');
		
		$m->group(array('prefix' => 'about', 'data-role' => 'navigation'), function($a){
		
			$a->add('Who we are', 'who-we-are?');
			$a->add('What we do?', 'what-we-do');
			$a->add('Our Goals', 'our-goals');
		});
	});
	
});
?>

如果我们将其渲染为 ul

<ul>
	...
	<li data-info="test">
		<a href="http://yourdomain.com/pages/about">About</a>
		<ul>
			<li data-info="test" data-role="navigation"><a href="http://yourdomain.com/pages/about/who-we-are"></a></li>
			<li data-info="test" data-role="navigation"><a href="http://yourdomain.com/pages/about/what-we-do"></a></li>
			<li data-info="test" data-role="navigation"><a href="http://yourdomain.com/pages/about/our-goals"></a></li>
		</ul>
	</li>
</ul>

元数据

在您需要为每个项目附加一些元数据的情况下,可能会遇到一些情况;这些数据可以是任何东西,从项目放置顺序到访问项目所需的权限;您可以通过使用 data() 方法来完成此操作。

data() 方法与 attr() 方法完全相同。

如果您使用一个参数调用 data(),它将为您返回数据值。如果您使用两个参数调用它,它将考虑第一个和第二个参数作为键/值对并设置数据。如果您需要一步添加多个键/值对,也可以传递数据关联数组;最后,如果您不带任何参数调用它,它将以数组形式返回所有数据。

<?php
Menu::make('MyNavBar', function($menu){

  // ...
  
  $menu->add('Users', array('route'  => 'admin.users'))
       ->data('permission', 'manage_users');

});
?>

您也可以像访问属性一样访问数据。

<?php
	
	//...
	
	$menu->add('Users', '#')->data('placement', 12);
	
	// you can refer to placement as if it's a public property of the item object
	echo $menu->users->placement;    // Output : 12
	
	//...
?>

元数据不会对项目执行任何操作,也不会在HTML中渲染。开发者将决定如何使用它们。

如果您需要针对一组项目,可以在集合上使用 data

<?php
  // ...
  $menu->add('Users', 'users');
  
  $menu->users->add('New User', 'users/new');
  $menu->users->add('Uses', 'users');
  
  // add a meta data to children of Users
  $menu->users->children()->data('anything', 'value');
  
  // ...

过滤项

我们可以使用 filter() 方法通过一个闭包来过滤菜单项。Filter() 接收一个您定义的闭包。然后它遍历项目并对每个项目运行您的闭包。

对于要排除的项目,您必须返回 false,对于要保留的项目,您必须返回 true

让我们用一个现实世界的场景来继续。

我猜您的 User 模型可以检查用户是否有特定的权限。

<?php
Menu::make('MyNavBar', function($menu){

  // ...
  
  $menu->add('Users', array('route'  => 'admin.users'))
       ->data('permission', 'manage_users');

})->filter(function($item){
  if(User::get()->can( $item->data('permission'))) {
      return true;
  }
  return false;
});
?>

如您所注意到的,我们使用 data() 为每个项目附加了所需的权限。

因此,具有 manage_users 权限的用户将可以看到 Users 项目。

排序项

laravel-menu 可以根据用户定义的函数或键对项目进行排序,该键可以是项目的属性,如 id、parent 等,或与每个项目一起存储的元数据。

要根据属性和/或元数据对项目进行排序

<?php
Menu::make('main', function($m){

	$m->add('About', '#')     ->data('order', 2);
	$m->add('Home', '#')      ->data('order', 1);
	$m->add('Services', '#')  ->data('order', 3);
	$m->add('Contact', '#')   ->data('order', 5);
	$m->add('Portfolio', '#') ->data('order', 4);

})->sortBy('order');		
?>

sortBy() 还接收第二个参数,指定排序方向:升序(asc)和降序(dsc)。

默认值为 asc

按降序对 Id 进行排序

<?php
Menu::make('main', function($m){

	$m->add('About');
	$m->add('Home');
	$m->add('Services');
	$m->add('Contact');
	$m->add('Portfolio');

})->sortBy('id', 'desc');		
?>

通过传递闭包对项目进行排序

<?php
Menu::make('main', function($m){

	$m->add('About')     ->data('order', 2);
	$m->add('Home')      ->data('order', 1);
	$m->add('Services')  ->data('order', 3);
	$m->add('Contact')   ->data('order', 5);
	$m->add('Portfolio') ->data('order', 4);

})->sortBy(function($items) {
	// Your sorting algorithm here...
	
});		
?>

闭包接受项目集合作为参数。

渲染方法

默认提供多种渲染格式。

将菜单作为无序列表渲染

  {!! $MenuName->asUl() !!}

asUl() 将将您的菜单渲染为无序列表。它还接受一个可选参数来定义 <ul> 标签的属性。

{!! $MenuName->asUl( array('class' => 'awesome-ul') ) !!}

结果

<ul class="awesome-ul">
  <li><a href="http://yourdomain.com">Home</a></li>
  <li><a href="http://yourdomain.com/about">About</a></li>
  <li><a href="http://yourdomain.com/services">Services</a></li>
  <li><a href="http://yourdomain.com/contact">Contact</a></li>
</ul>

将菜单作为有序列表渲染

  {!! $MenuName->asOl() !!}

asOl() 方法将您的菜单渲染为有序列表。它还接受一个可选参数来定义 <ol> 标签的属性。

{!! $MenuName->asOl( array('class' => 'awesome-ol') ) !!}

结果

<ol class="awesome-ol">
  <li><a href="http://yourdomain.com">Home</a></li>
  <li><a href="http://yourdomain.com/about">About</a></li>
  <li><a href="http://yourdomain.com/services">Services</a></li>
  <li><a href="http://yourdomain.com/contact">Contact</a></li>
</ol>

将菜单作为 div 渲染

  {!! $MenuName->asDiv() !!}

asDiv() 方法将您的菜单作为嵌套HTML div渲染。它还接受一个可选参数来定义父 <div> 标签的属性。

{!! $MenuName->asDiv( array('class' => 'awesome-div') ) !!}

结果

<div class="awesome-div">
  <div><a href="http://yourdomain.com">Home</a></div>
  <div><a href="http://yourdomain.com/about">About</a></div>
  <div><a href="http://yourdomain.com/services">Services</a></div>
  <div><a href="http://yourdomain.com/contact">Contact</a></div>
</div>

将菜单作为 Bootstrap 3 导航栏渲染

Laravel Menu 默认提供部分视图,它以Bootstrap友好的样式生成菜单项,您可以将其 包含 在基于Bootstrap的导航栏中。

您可以通过 config('laravel-menu.views.bootstrap-items') 访问部分视图。

您需要做的就是包含部分视图,并将根级项目传递给它。

...

@include(config('laravel-menu.views.bootstrap-items'), array('items' => $mainNav->roots()))

...

您的Bootstrap代码将看起来像这样

<nav class="navbar navbar-default" role="navigation">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">

       @include(config('laravel-menu.views.bootstrap-items'), array('items' => $mainNav->roots()))

      </ul>
      <form class="navbar-form navbar-right" role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">

        @include(config('laravel-menu.views.bootstrap-items'), array('items' => $loginNav->roots()))

      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>

高级用法

如前所述,您可以创建自己的渲染格式。

基本示例

如果您想根据您的设计渲染菜单(s),您应该创建两个视图。

  • View-1 这个视图包含所有HTML代码,如 navuldiv 标签,它们封装了菜单项。
  • View-2 这个视图实际上是一个部分视图,负责渲染菜单项(它将被包含在 View-1 中)。

在这里我们使用两个视图文件的原因是 View-2 会递归调用自身以渲染多层菜单所需的 deepest 级别的项。

让我们用一个例子来简化这个过程

在我们的 app/Http/routes.php

<?php
Menu::make('MyNavBar', function($menu){
  
  $menu->add('Home');
  
   $menu->add('About',    array('route'  => 'page.about'));
   
   $menu->about->add('Who are we?', 'who-we-are');
   $menu->about->add('What we do?', 'what-we-do');

  $menu->add('services', 'services');
  $menu->add('Contact',  'contact');
  
});
?>

在这个例子中,我们将 View-1 命名为 custom-menu.blade.php,将 View-2 命名为 custom-menu-items.blade.php

custom-menu.blade.php

<nav class="navbar">
  <ul class="horizontal-navbar">
    @include('custom-menu-items', array('items' => $MyNavBar->roots()))
  </ul>
</nav><!--/nav-->

custom-menu-items.blade.php

@foreach($items as $item)
  <li @if($item->hasChildren()) class="dropdown" @endif>
      <a href="{!! $item->url() !!}">{!! $item->title !!} </a>
      @if($item->hasChildren())
        <ul class="dropdown-menu">
              @include('custom-menu-items', array('items' => $item->children()))
        </ul> 
      @endif
  </li>
@endforeach

让我们描述一下上面的操作,在 custom-menus.blade.php 中,我们根据设计放置了任何HTML模板代码,然后包含了 custom-menu-items.blade.php 并将 root level 的菜单项传递给 custom-menu-items.blade.php

...
@include('custom-menu-items', array('items' => $menu->roots()))
...

custom-menu-items.blade.php 中,我们运行了一个 foreach 循环,并在当前项有子项时递归调用文件。

要将渲染的菜单放入您的应用程序模板中,您只需在主布局中包含 custom-menu 视图。

Blade 控制结构

Laravel 菜单扩展 Blade 以处理特殊布局。

@lm-attrs

您可能会遇到一些 HTML 属性被明确地写入视图内部而不是在添加项时动态定义的情况;然而,您需要将这些静态属性与项的属性合并。

@foreach($items as $item)
  <li @if($item->hasChildren()) class="dropdown" @endif data-test="test">
      <a href="{!! $item->url() !!}">{!! $item->title !!} </a>
      @if($item->hasChildren())
        <ul class="dropdown-menu">
              @include('custom-menu-items', array('items' => $item->children()))
        </ul> 
      @endif
  </li>
@endforeach

在上面的代码片段中,li 标签具有类 dropdown 和在视图中明确定义的 data-test 属性;Laravel 菜单提供了一种控制结构来处理这种情况。

假设项也有在添加时动态定义的几个属性

<?php
// ...
$menu->add('Dropdown', array('class' => 'item item-1', 'id' => 'my-item'));
// ...

视图

@foreach($items as $item)
  <li@lm-attrs($item) @if($item->hasChildren()) class="dropdown" @endif data-test="test" @lm-endattrs>
      <a href="{!! $item->url !!}">{!! $item->title !!} </a>
      @if($item->hasChildren())
        <ul class="dropdown-menu">
              @include('custom-menu-items', array('items' => $item->children()))
        </ul> 
      @endif
  </li>
@endforeach

这个控制结构会自动将静态 HTML 属性与动态定义的属性合并。

这里是结果

...
<li class="item item-1 dropdown" id="my-item" data-test="test">...</li>
...

配置

您可以在 config/settings.php 文件中调整菜单构建器的行为。目前它提供了一些开箱即用的选项

  • auto_activate 根据当前 URI 自动激活菜单项
  • activate_parents 激活活动项的父项
  • active_class 活动项的默认 CSS 类名
  • restful 激活 RESTful URL。例如,resource/slug 将激活具有 resource URL 的项。
  • cascade_data 如果您需要项的后代继承其父项的元数据,请确保此选项已启用。
  • rest_base 所有 RESTful 资源可能需要添加的前缀的基本 URL。
  • active_element 您可以选择要添加激活类(锚点或包装元素)的 HTML 元素。

您还可以覆盖每个菜单的默认设置。要覆盖菜单的设置,只需将小写的菜单名称作为键添加到设置数组中,并添加您需要覆盖的选项

<?php
return array(
	'default' => array(
		'auto_activate'    => true,
		'activate_parents' => true,
		'active_class'     => 'active',
		'active_element'   => 'item',    // item|link
		'restful'          => true,
	),
	'yourmenuname' => array(
		'auto_activate'    => false
	),
);

如果您需要帮助

请使用 GitHub issues 提交所有问题和疑问,我将尽力帮助您。

许可证

Laravel-Menu 是在 MIT 许可条款下分发的免费软件。