Сам вывод на экран пунктов меню без оформления стилей выглядит следующим образом:

Установка.
Процесс установки подробно описан тут. Для этого выполняем в консоли (перейдя в каталог проекта) командуcomposer require lavary/laravel-menu
далее добавляем пункт в массив провайдеров (файл config/app.php)
'Lavary\Menu\ServiceProvider',и в массив алиасов:
'Menu' => 'Lavary\Menu\Facade',
Базовое использование.
Расширение имеет много полезных методов, которые могут пригодиться при создании сложных меню. В моем примере будут описаны только самые важные.Информацию относящуюся к меню лучше всего хранить в БД. То есть создаем таблицу «menus» с такой структурой (минимально):

для дочерних пунктов меню прописывается id их родительских пунктов в поле parent_id.
В поле path нужно прописать ссылки на страницы к которым относятся данные пункты.
Конечно нужно создать модель для работы с данной таблицей. Для этого в консоли:
php artisan make:model Menu
Функционал по созданию пунктов меню с помощью данного расширения лучше всего вынести в отдельный класс или в метод главного (наследуемого) контроллера. Т.к. меню должно формироваться не для одного контроллера, а для многих (возможно для всех).
Для того, чтобы использовать расширение, сначала получаем данные о пунктах меню из БД используя модель. Для этого в нужном методе контроллера (который должен вывести страницу с нашим меню) получаем данные из таблицы menus в таком формате:

и передаем их на обработку методу buildMenu().
То есть, действие контроллера будет содержать такой код:
public function index() { $arrMenu = \App\Menu::all(); $menu = $this->buildMenu($arrMenu); return view('home', ['menu' => $menu]); }
Метод buildMenu() создающий пункты меню:
use Menu as LavMenu; //lavary/laravel-menu ... /* * Формирование пунктов меню используя расширение * https://github.com/lavary/laravel-menu#installation */ public function buildMenu ($arrMenu){ $mBuilder = LavMenu::make('MyNav', function($m) use ($arrMenu){ foreach($arrMenu as $item){ /* * Для родительского пункта меню формируем элемент меню в корне * и с помощью метода id присваиваем каждому пункту идентификатор */ if($item->parent_id == 0){ $m->add($item->title, $item->path)->id($item->id); } //иначе формируем дочерний пункт меню else { //ищем для текущего дочернего пункта меню в объекте меню ($m) //id родительского пункта (из БД) if($m->find($item->parent_id)){ $m->find($item->parent_id)->add($item->title, $item->path)->id($item->id); } } } }); return $mBuilder; }
Методу make(), в качестве первого аргумента, передается произвольное название меню. Название нужно для того, чтобы была возможность создавать дополнительные меню, например в боковой панели. В качестве второго аргумента передается анонимная функция. Чтобы получить доступ к данным полученным из модели, даем к ним доступ с помощью
use ($arrMenu)
Результат работы метода buildMenu() сохраняется в переменной $menu, которая будет содержать объект Builder, и далее передаем ее в шаблон наряду с другими переменными.
В данном действии контроллера (index) вызывается шаблон 'home' - файл resources\views\home.blade.php. В нем секция отвечающая за меню будет иметь такой вид:
@extends('layouts.app') @section('menu') @if($menu) <div class="menu classic"> <ul id="nav" class="menu"> <!--$menu->roots() - получаем только родительские элементы меню--> @include('customMenuItems', ['items'=>$menu->roots()]) </ul> </div> @endif @endsectionгде HTML код и классы можно настроить под оформление своего проекта.
Как тут видно, шаблон наследует от макета, который располагается в resources\views\layouts\app.blade.php
в макете секцию меню нужно подключить как и остальные блоки:
@yield('menu')
Пункты меню будем выводить в дополнительном, подключаемом шаблоне, это нужно для создания многоуровневого меню – шаблон будет рекурсивно вызывать сам себя для формирования дочерних пунктов меню неограниченной вложенности. Для подключение данного подшаблона прописана директива
@include('customMenuItems', ['items'=>$menu->roots()])которая подключит шаблон resources\views\customMenuItems.blade.php и передаст в переменной items массив объектов только родительских пунктов меню.
<!--Шаблон для вывода меню с использованием рекурсии--> @foreach($items as $item) <!--Добавляем класс active для активного пункта меню--> <li {{ (URL::current() == $item->url()) ? "class=active" : '' }}> <!-- метод url() получает ссылку на пункт меню (указана вторым параметром при создании объекта LavMenu)--> <a href="{{ $item->url() }}">{{ $item->title }}</a> <!--Формируем дочерние пункты меню метод haschildren() проверяет наличие дочерних пунктов меню--> @if($item->hasChildren()) <ul class="sub-menu"> <!--метод children() возвращает дочерние пункты меню для текущего пункта--> @include(env('THEME').'.customMenuItems', ['items'=>$item->children()]) </ul> @endif </li> @endforeach
Активному пункту меню присваивается класс active для того, чтобы придать ему определенное оформление, при надобности.
Для каждого пункта меню проверяется наличие дочерних элементов и если они есть, то шаблон подключается рекурсивно для формирования вложенности пунктов меню.
После установки композером запись в файлу composer.json не появилась, добавли вручную и обновил композер. в конфиг все добавил и в контроллере написал use Menu
Почему появляется ошибка?
ответ на комментарий Владимир от 18.08.2017
Проверьте наличие данного файла по указанному пути:
ответ на комментарий Сергей от 18.08.2017
подключаю не как у вас в примере, а:
Все работает, Но как только обращаюсь к методу make
выдает ошибку:
Подскажите, в чем может быть дело? хотяб куда копать.. любая информация будет полезна
ответ на комментарий sam от 26.09.2017
Только, почему то, создается объект Illuminate\Database\Eloquent\Builder, а должен Lavary\Menu\Builder данного расширения, который не требует передачу массива (см. файл vendor\lavary\laravel-menu\src\Lavary\Menu\Menu.php).
Возможно неправильно подключили и метод make() вызывается не у того объекта.
Попробуйте перед вызовом данного метода выполнить строку:
должно отобразиться : "Menu". Т.е. нужно понять почему вызывается не тот Builder.
ответ на комментарий Сергей от 26.09.2017
спасибо за ответ. буду разбираться..
ответ на комментарий Сергей от 26.09.2017
нужно было, а у меня было:
Делаю по видео урокам и там у человека \Corp\Menu и работало.. пол дня провозился че только не делал...
Т.е. выводит только родительские пункты меню. И в шаблоне не выводит родителя, в dd($mBuilder) только родителя. Использую laravel 5.5. Ошибок не показывает.
ответ на комментарий Дмитрий от 19.10.2017
тогда как в базе данных (если следовали примеру) поле именуется "parent_id":
возможно поэтому.
ответ на комментарий Сергей от 19.10.2017
Я называл поля в базе - "parent". Не пойму где искать ошибку.
ответ на комментарий Дмитрий от 20.10.2017
Должна отобразиться коллекция, каждый элемент которой в свойстве "attributes" должен содержать parent_id (у вас parent). Стоит ли там правильный "id" у дочерних пунктов меню.
И если вложенность больше двух, это как-то регулируется?
Заранее, спасибо!
А вот вопрос, по поводу места формирования и передачи меню, еще на повестке дня)
ответ на комментарий Alena от 18.01.2018
Можно код формирования меню из шаблона home.blade.php (то, что внутри секции 'menu') прописать в самом макете, если оно нужно на всех страницах сайта.
ответ на комментарий Сергей от 18.01.2018
ответ на комментарий Сергей от 18.01.2018
ответ на комментарий Alena от 19.01.2018
Не понял, что вы понимаете под «меню вынесено в отдельный лейаут». Отдельный layout создают для специфических страниц сайта, когда основной макет не устраивает, а меню тут ни при чем. Меню надо вынести в отдельный шаблон, а не макет и подключить его во всех ваших макетах (если их несколько), раз уж оно нужно на всех страницах или в другом шаблоне, который будет подключен во всех макетах.
На счет контроллера для формирования и передачи меню в шаблон – есть разные способы. Можно формировать его в главном контроллере, от которого будут наследовать остальные. На крайний случай app\Http\Controllers\Controller.php. Формируете там переменную $menu с данными и сохраняете в свойстве контроллера. Далее есть варианты:
- можно в каждом дочернем контроллере получать из свойства данные по меню и отправлять в шаблон данного контроллера. Это годится если контроллеров и действий совсем мало.
- создать в родительском контроллере метод (например renderOutput), в который будут передаваться данные из дочерних контроллеров, в т.ч. название шаблона который нужно выводить. И уже главный контроллер будет вызывать return view(). При этом компоненты общие для всего сайта формируются как раз в родительском контроллере.
ответ на комментарий Сергей от 19.01.2018
Не совсем поняла второй вариант, не затруднит ли Вас написать пример, заранее весьма благодарна!
ответ на комментарий Alena от 19.01.2018
Я сделала через View::composer()
В этом видео подсмотрела, оставлю здесь, может кому-нибудь еще пригодится
так и не понял как использовать:
if( $menu->about->hasChildren() ) {
// Do something
}
у меня в меню у элемента с дочерними элементами другой класс поэтому надо определить
есть у элемента потомки или нет ,
в данной конструкции что должно быть на месте 'about' ?
ответ на комментарий Oleg от 16.02.2018
$menu->about или $item (у меня) это объект текущего пункта меню (Lavary\Menu\Item) для которого нужно определить есть ли у него дочерние пункты.
"у меня в меню у элемента с дочерними элементами другой класс" - не понятно какой может быть другой класс, если используется расширение.
ответ на комментарий Сергей от 16.02.2018
я сделал архив:
http://dropmefiles.com/GLfhp
ответ на комментарий Oleg от 17.02.2018
сделайте по моему примеру.
ответ на комментарий Артур от 27.03.2018