Мега Меню с 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
Другие вопросы по тегам