Yii2 как с базы вывести категории когда у них есть подкатегориии с подкатегориями?

Всем доброй ночи!

Вот так как на картинки хочу вывести свои категории, но я че та запутался с foreach и голова уже худом идет.
c2deaab9fe5345f08d3dc5836cc3d3af.png
Как видно на картинки там есть
1 Спойлер это названия категории
2 У категории есть подкатегория, то она без чекбокса, если у подкатегории есть свои подкатегории то они становятся чебоксами

Подскажите пожалуйста как это грамотно реализовать!

Пример моей бд как я храню свои категории:

id | parent_id | title
1 | 0 | Реклама
2 | 0 | Автоуслуги
3 | 1 | Настройка контекстной рекламы
4 | 3 | SEO оптимизация сайта
5 | 3 | Реклама в социальных сетях
6 | 1 | Услуги промоутеров
7 | 6 | Мерчендайзер
9 | 6 | Промоутер в супермаркет
10| 6 | Социологические опросы
11| 2 | Кузовной ремонт
12| 2 | Эвакуатор
13| 2 | Зарядка аккумулятора
... | ...... | ......................................

Как я хочу чтоб было
menu
     - menu
          - menu
          - menu
     - menu
          - menu
          - menu
menu
     - menu
          - menu
          - menu
     - menu
          - menu
          - menu


Заранее спасибо!
  • Вопрос задан
  • 1521 просмотр
Пригласить эксперта
Ответы на вопрос 2
Steein
@Steein
Программист
$menu = Array( // Предполагалось, что он SQL SELECT
  Array('id'=>1,'title'=>'Menu 1',          'parent_id'=>null),
  Array('id'=>2,'title'=>'Sub 1.1',         'parent_id'=>1),
  Array('id'=>3,'title'=>'Sub 1.2',         'parent_id'=>1),
  Array('id'=>4,'title'=>'Sub 1.3',         'parent_id'=>1),
  Array('id'=>5,'title'=>'Menu 2',          'parent_id'=>null),
  Array('id'=>6,'title'=>'Sub 2.1',         'parent_id'=>5),
  Array('id'=>7,'title'=>'Sub Sub 2.1.1',   'parent_id'=>6),
  Array('id'=>8,'title'=>'Sub 2.2',         'parent_id'=>5),
  Array('id'=>9,'title'=>'Menu 3',          'parent_id'=>null),
);


function has_children($rows,$id) {
  foreach ($rows as $row) {
    if ($row['parent_id'] == $id)
      return true;
  }
  return false;
}
function build_menu($rows,$parent=0)
{  
  $result = "<ul>";
  foreach ($rows as $row)
  {
    if ($row['parent_id'] == $parent){
      $result.= "<li>{$row[title]}";
      if (has_children($rows,$row['id']))
        $result.= build_menu($rows,$row['id']);
      $result.= "</li>";
    }
  }
  $result.= "</ul>";

  return $result;
}
echo build_menu($menu);


<ul>
  <li>Menu 1<ul>
    <li>Sub 1.1</li>
    <li>Sub 1.2</li>
    <li>Sub 1.3</li>
  </ul></li>
  <li>Menu 2<ul>
    <li>Sub 2.1<ul>
      <li>Sub Sub 2.1.1</li>
    </ul></li>
    <li>Sub 2.2</li>
  </ul></li>
  <li>Menu 3</li>
</ul>
Ответ написан
Uman
@Uman Автор вопроса
PHP, YII2
Нужно сделать виджет, создаем папку componets, а там СОЗДАЕМ ФАЙЛ CategoryWidget.php

ниже представлен код

<?php

namespace app\components;

use Yii;
use yii\base\Widget;
use app\models\Category;

class CategoryWidget extends Widget
{
    public $tpl;
    public $model;
    public $data;
    public $tree;
    public $menuHtml;

    public function init()
    {
        parent::init();
        if ($this->tpl === null) {
            $this->tpl = 'category';
        }
        $this->tpl .= '.php';
    }

    public function run()
    {
        // get cache
//        if ($this->tpl == 'category.php') {
//            $menu = Yii::$app->cache->get('category');
//            if ($menu) return $menu;
//        }

        $this->data = Category::find()
            ->indexBy('id')
            ->orderBy('sortOrder')
            ->asArray()
            ->all();
        $this->tree = $this->getTree();
        $this->menuHtml = $this->getMenuHtml($this->tree);
        // set cache
//        if ($this->tpl == 'category.php') {
//            Yii::$app->cache->set('category', $this->menuHtml, 60);
//        }
        return $this->menuHtml;
    }

    protected function getTree()
    {
        $tree = [];

        foreach ($this->data as $id => &$node) {
            if (!$node['parent_id']) {
                $tree[$id] = &$node;
            } else {
                $this->data[$node['parent_id']]['children'][$node['id']] = &$node;
            }
        }
        return $tree;
    }

    protected function getMenuHtml($tree){
        $str = '';
        foreach ($tree as $category) {
            $str .= $this->catToTemplate($category);
        }
        return $str;
    }

    protected function catToTemplate($category)
    {
        ob_start();
        include __DIR__ . '/category_tpl/' . $this->tpl;
        return ob_get_clean();
    }

}


потом в папке components создаем еще одну папку называем category_tpl, там создаем файл category.php

ниже представлен код

<?= $category['title'] ?>
            <?php if (isset($category['children'])): ?><br/>
                <?= $this->getMenuHtml($category['children']) ?>
            <?php endif; ?>


Потом во вьюхе делаем рендер виджета

<?= CategoryWidget::widget(['tpl' => 'category']) ?>
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы