Мега Меню с PHP в Laravel
РЕДАКТИРОВАТЬ: на основе совета Тома, вот мой модифицированный код. Работает хорошо, так что спасибо Тому.
<?php
$categories = Category::where('parent_id', '0')->get();
foreach($categories as $category):
$category_courses = get_courses($category->id);
$sub_categories = Category::where('parent_id', $category->id)->get();
$max_iteration = ceil(count($sub_categories) / 4);
?>
<li class="dropdown mega-menu-4">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" title="{{ $category->name }}">{{ $category->name }} <b class="caret"></b></a>
<ul class="dropdown-menu style-plain">
<li class="one-column">
<?php foreach($sub_categories as $key=>$sub_category): ?>
<ul>
<li class="nav-title">{{ $sub_category->name }}</li>
<?php foreach(get_courses($sub_category->id) as $course): ?>
<li>{{ $course->title }}</li>
<?php endforeach; ?>
</ul>
<?php if(($key + 1) % $max_iteration == 0): ?>
</li>
<li class="one-column">
<?php endif; ?>
<?php endforeach; ?>
</li>
</ul>
</li>
<?php endforeach; ?>
Хотя теперь я думаю, что мне нужно создать дерево в памяти после получения совета от мачуги в #laravel IRC. По сути на основе этого SO ответ Flat PHP Array to Hierarchy Tree.
Я пытаюсь создать мега-меню в своем приложении Laravel со следующей структурой, чтобы оно хорошо работало с Bootstrap 2.3.
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<div class="nav-collapse collapse">
<ul class="nav">
<li class="dropdown mega-menu-4 transition">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">$category <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class="one-column">
<ul>
<li class="nav-title">$subCategory 1</li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
</ul>
<ul>
<li class="nav-title">$subCategory 1</li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
</ul>
</li>
<li class="one-column">
<ul>
<li class="nav-title">$subCategory 2</li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
</ul>
<ul>
<li class="nav-title">$subCategory 2</li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
</ul>
</li>
<li class="one-column">
<ul>
<li class="nav-title">$subCategory 3</li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
</ul>
<ul>
<li class="nav-title">$subCategory 3</li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
</ul>
</li>
<li class="one-column">
<ul>
<li class="nav-title">$subCategory 4</li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
</ul>
<ul>
<li class="nav-title">$subCategory 4</li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
<li><a href="#">$course</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
В моей базе данных у меня есть следующее:
table: categories
fields: id, parent_id, name, slug
table: courses
fields: id, category_id, title, slug
Я борюсь с логикой цикла for и foreach, чтобы генерировать элементы ul внутри элементов li: one-column. Я хочу максимум 4 столбца с таким количеством строк, сколько необходимо, в зависимости от количества подкатегорий.
Таким образом, в таблице категорий для категории верхнего уровня не будет назначен "parent_id", а для подкатегории будет назначен "родительский_ид" верхнего уровня.
Таким образом, я могу использовать $ category как $ category и настроить структуру меню верхнего уровня, которая создаст элемент li: dropdown для каждой категории верхнего уровня. Проблема возникает при попытке реализовать элементы li: one-column. Каждый элемент li: one-column по сути является столбцом в мегаменю, поэтому мне нужно максимум четыре. Каждый ul в столбце является подкатегорией.
Поэтому, если под категорией верхнего уровня есть 13 подкатегорий, каждый столбец будет иметь следующее:
Column 1: 4
Column 2: 3
Column 3: 3
Column 4: 3
Затем, если новая подкатегория была добавлена, это будет:
Column 1: 4
Column 2: 4
Column 3: 3
Column 4: 3
И так далее. Таким образом, каждая новая подкатегория будет заполнять следующий доступный столбец.
Вероятно, есть действительно простое решение, но сейчас я борюсь с логикой. Заранее спасибо.
РЕДАКТИРОВАТЬ: я все ближе, используя:
<ul class="nav">
@foreach($categories as $category)
<?php
$category_courses = get_courses($category->id);
$sub_categories = Category::where('parent_id', $category->id)->get();
$sub_categories_total = count($sub_categories); // int(5)
$sub_category_split = round($sub_categories_total / 4); // int(1)
?>
<li class="dropdown mega-menu-4">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" title="{{ $category->name }}">{{ $category->name }} <b class="caret"></b></a>
<ul class="dropdown-menu style-plain">
@for($i=0; ++$i <=4;)
<li class="one-column">
@foreach($sub_categories as $sub_category)
<ul >
<li class="nav-title">{{ $sub_category->name }}</li>
@foreach(get_courses($sub_category->id) as $course)
<li>{{ $course->title }}</li>
@endforeach
</ul>
@endforeach
</li>
@endfor
</ul>
</li>
@endforeach
</ul>
Я все еще не совсем там, хотя он добавляет все sub_categories к каждому элементу li: one-column. Я чувствую, что, конечно, ближе к решению.
РЕДАКТИРОВАТЬ: ОК, я сейчас намного ближе. Теперь я могу вывести только максимальную итерацию в каждом элементе li: one-column, но он выводит точно такие же данные. Мне нужен способ продолжить цикл foreach от того места, где он разрывается.
<ul class="nav">
@foreach($categories as $category)
<?php
$category_courses = get_courses($category->id);
$sub_categories = Category::where('parent_id', $category->id)->get();
$max_iteration = round(count($sub_categories) / 4);
?>
<li class="dropdown mega-menu-4">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" title="{{ $category->name }}">{{ $category->name }} <b class="caret"></b></a>
<ul class="dropdown-menu style-plain">
@for($ci=0; ++$ci <=4;)
<li class="one-column">
@foreach($sub_categories as $key=>$sub_category)
@if($key <= $max_iteration)
<ul >
<li class="nav-title">{{ $sub_category->name }}</li>
@foreach(get_courses($sub_category->id) as $course)
<li>{{ $course->title }}</li>
@endforeach
</ul>
@else
<?php break; ?>
@endif
@endforeach
</li>
@endfor
</ul>
</li>
@endforeach
</ul>
РЕДАКТИРОВАТЬ: ОК, это самый близкий у меня до сих пор, и он почти там. Тем не менее, все еще не правильно, поскольку он выводит 1 подкатегорию в первом столбце, столбце 2, столбце 3, но 2 в столбце 4.:-(
@foreach($categories as $category)
<?php
$category_courses = get_courses($category->id);
$sub_categories = Category::where('parent_id', $category->id)->get();
$max_iteration = round(count($sub_categories) / 4) + 1;
?>
<li class="dropdown mega-menu-4">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" title="{{ $category->name }}">{{ $category->name }} <b class="caret"></b></a>
<ul class="dropdown-menu style-plain">
<li class="one-column">
@foreach($sub_categories as $key=>$sub_category)
<ul>
<li class="nav-title">{{ $sub_category->name }}</li>
@foreach(get_courses($sub_category->id) as $course)
<li>{{ $course->title }}</li>
@endforeach
</ul>
@if($key <= $max_iteration)
</li>
<li class="one-column">
@endif
@endforeach
</li>
</ul>
</li>
@endforeach
2 ответа
Вам нужно сделать 2 изменения, чтобы добиться этого. Во-первых, вам может понадобиться ceil
вместо round
для тебя $max_iteration
переменная. Это гарантирует, что ваши столбцы всегда будут разделены в одном месте.
Затем измените эту строку...
@if($key <= $max_iteration)
в
@if(($key + 1) % $max_iteration == 0)
$key - это ключ, начинающийся с нуля, поэтому вам нужно увеличить его, поскольку мы имеем дело с количествами, начинающимися с 1. Затем, проверяя его остаток при делении на $max_iteration
мы можем сказать, достигли ли мы следующего столбца. Это будет ноль, когда ключ кратен максимальной итерации.
Поняв немного больше, что вы ищете, я думаю, что это может быть более уместным, поэтому подумайте об этом как об отделителе:
@foreach($categories as $category)
<?php
$category_courses = get_courses($category->id);
$sub_categories = Category::where('parent_id', $category->id)->get();
$max_iteration = round(count($sub_categories) / 4);
?>
<li class="dropdown mega-menu-4">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" title="{{ $category->name }}">{{ $category->name }} <b class="caret"></b></a>
<ul class="dropdown-menu style-plain">
<li class="one-column">
<?php $counter = 0 ?>
@foreach($sub_categories as $key=>$sub_category)
<?php $counter++ ?>
@if($counter == $max_iteration)
</li>
<li class="one-column">
<?php $counter = 0;?>
@endif
<ul >
<li class="nav-title">{{ $sub_category->name }}</li>
@foreach(get_courses($sub_category->id) as $course)
<li>{{ $course->title }}</li>
@endforeach
</ul>
@endforeach
</li>
</ul>
</li>
@endforeach