Русскоязычный форум, посвященный фреймворку Kohana

Все о фреймворке Kohana. Обсуждение уроков, документации.
Текущее время: 10 ноя 2024, 14:13

Часовой пояс: UTC + 4 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 12 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Иерархическое меню
СообщениеДобавлено: 28 июл 2012, 13:50 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 24 июл 2012, 18:00
Сообщения: 701
Откуда: Murom, Russia
Всем привет!

Не совсем уверен, что написал в нужной ветке.
Модератор, перенеси тему в нужную ветку если что )

Тут строю иерархическое меню, беря пункты с базы данных и в общем то получилось, но есть нюанс.
Запутался совсем в том что получилось. Помогите исправить косяк..

Должно получится вот что:
Изображение

Когда я верстал это меню у меня получился такой html:

Код:
<ul>
  <li>Родитель 1</li>
  <li>
    <ul>
      <li>Пункт 1<li>
      <li>Пункт 2<li>
      ...
    </ul>
  </li>
  <li>Родитель 2</li>
  <li>
    <ul>
      <li>Пункт 1<li>
      <li>Пункт 2<li>
      ...
    </ul>
  </li>
  <li>Родитель 3</li>
  <li>
    <ul>
      <li>Пункт 1<li>
      <li>Пункт 2<li>
      ...
    </ul>
  </li>
  <li>Родитель 4</li>
  <li>
    <ul>
      <li>Пункт 1<li>
      <li>Пункт 2<li>
      ...
    </ul>
  </li>
</ul>


Когда начал это дело реализовывать в кохане появились проблемы.

Вот структура таблицы этих категорий:
Код:
CREATE TABLE IF NOT EXISTS `categories` (
  `id` SMALLINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,
  `parent_id` SMALLINT(8) UNSIGNED NOT NULL DEFAULT 0,
  `category` VARCHAR(60) NOT NULL COMMENT 'Category title',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_category` (`category`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


Вот так я её заполнил:
Код:
INSERT INTO `categories` (`id`, `parent_id`, `category`) VALUES
  ( 1, 0, 'Одежда'),
  ( 2, 0, 'Сумки'),
  ( 3, 0, 'Обувь'),
  ( 4, 0, 'Аксессуары'),

  ( 5, 1, 'Жакеты'),
  ( 6, 1, 'Жилеты'),
  ( 7, 1, 'Куртки'),
  ( 8, 1, 'Футболки'),
  ( 9, 1, 'Платья'),
  (10, 1, 'Плащи'),
  (11, 1, 'Топы'),

  (12, 2, 'Большие сумки'),
  (13, 2, 'Дорожные сумки'),
  (14, 2, 'Дорожные косметички'),
  (15, 2, 'Рюкзаки'),
  (16, 2, 'Портфели'),
  (17, 2, 'Клатчи'),
  (18, 2, 'Сумки на ремне'),
  (19, 2, 'Сумки с ручками'),
  (20, 2, 'Сумки-портфели'),

  (21, 3, 'Ботинки'),
  (22, 3, 'Кроссовки'),
  (23, 3, 'Лоферы'),
  (24, 3, 'Сандали'),
  (25, 3, 'Сапоги'),
  (26, 3, 'Балетки'),
  (27, 3, 'Обувь на платформе'),
  (28, 3, 'Обувь на каблуке'),

  (29, 4, 'Брелоки'),
  (30, 4, 'Гаджеты'),
  (31, 4, 'Галстуки'),
  (32, 4, 'Кошельки'),
  (33, 4, 'Ремни'),
  (34, 4, 'Головные уборы');


Вот моя модель (не обращайте внимание не дополнительные условия выборки из бд):
Код:
  public function get_tree($sex)
  {
    $sql =  "SELECT " . $this->_tableCategories . ".`id` AS 'ID'," . $this->_tableCategories . ".`parent_id` AS 'PARENT', " . $this->_tableSex . ".`sex` AS SEX, " . $this->_tableCategories . ".`category` AS 'CATEGORY'" .
            " FROM " . $this->_tableCategories . ", " . $this->_tableCatSex . ", " . $this->_tableSex .
            " WHERE " . $this->_tableCategories . ".`id` = " . $this->_tableCatSex . ".`category_id`" .
            " AND " . $this->_tableCatSex . ".`sex_id` = " . $this->_tableSex . ".`id`" .
            " AND " . $this->_tableSex . ".`sex` = :sex";

    return DB::query(Database::SELECT, $sql)
          ->parameters(array(':sex' => $sex))
          ->execute();
  }


В контролере всё очень просто:

Код:
  public function action_index ()
  {
    $name = $this->request->param('name');
    $id = $this->request->param('id');

    $this->tree = Model::factory('Page')->get_tree($name);

    if($id)
      $content = View::factory('/shop/category')
               ->bind('menu', $this->tree);
    else
      $content = View::factory('/shop/name')
               ->bind('menu', $this->tree)
               ->bind('name', $name);

    $this->template->content = $content;

    if ($name == 'man')
    {
      // TODO: Брать title из БД
      $this->template->title .= ' | ' . 'Мужчины';
    }
    else
    {
      // TODO: Брать title из БД
      $this->template->title .= ' | ' . 'Женщины';
    }
  }


В виде массив перебираю так:

Код:
  <div id="menu">
    <ul>
    <?php
      foreach($menu as $items_id => $items_val)
        // Если этого не сделать и пройтись форичем прямо по $items_val получается фигня какая-то
        $newmenu[] = $items_val;
      foreach($newmenu as $items_id => $items_val)
      {
        if($items_val['PARENT'] == 0)
          echo '<li>' . HTML::anchor('#', $items_val['CATEGORY']) . '</li>'."\n";
        echo '<li><ul>'."\n";
        foreach($newmenu as $p_items_val)
        {
          if($p_items_val['PARENT'] == $items_val['ID'])
            echo '<li>' . HTML::anchor(URL::site($items_val['SEX']) .'/category/' . $p_items_val['ID'], $p_items_val['CATEGORY']) . '</li>' ."\n";
        }
        echo '</ul></li>'."\n";
      }
    ?>
    </ul>
  </div>


И всё вроде хорошо, меню и для женского и для мужского разделов магазина генерируется правильно, иерархическое - подкатегория в категории. Но видимо с я циклом перемудрил. Потому что на выходе получился код такой (например мужской раздел) :

Код:
<ul>
    <li><a href="#">Одежда</a></li>
<li><ul>
<li><a href="/man/category/5">Жакеты</a></li>
<li><a href="/man/category/6">Жилеты</a></li>
<li><a href="/man/category/7">Куртки</a></li>
<li><a href="/man/category/8">Футболки</a></li>
</ul></li>
<li><a href="#">Сумки</a></li>
<li><ul>
<li><a href="/man/category/12">Большие сумки</a></li>
<li><a href="/man/category/13">Дорожные сумки</a></li>
<li><a href="/man/category/14">Дорожные косметички</a></li>
<li><a href="/man/category/15">Рюкзаки</a></li>
<li><a href="/man/category/16">Портфели</a></li>
</ul></li>
<li><a href="#">Обувь</a></li>
<li><ul>
<li><a href="/man/category/21">Ботинки</a></li>
<li><a href="/man/category/22">Кроссовки</a></li>
<li><a href="/man/category/23">Лоферы</a></li>
<li><a href="/man/category/24">Сандали</a></li>
<li><a href="/man/category/25">Сапоги</a></li>
</ul></li>
<li><a href="#">Аксессуары</a></li>
<li><ul>
<li><a href="/man/category/29">Брелоки</a></li>
<li><a href="/man/category/30">Гаджеты</a></li>
<li><a href="/man/category/31">Галстуки</a></li>
<li><a href="/man/category/32">Кошельки</a></li>
<li><a href="/man/category/33">Ремни</a></li>
<li><a href="/man/category/34">Головные уборы</a></li>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
<li><ul>
</ul></li>
    </ul>


В конце дофига пустых li и ul.

У кого опыта по больше, подскажите как правильно строить такое меню.
Может быть мне как то по другому вид/контролер/модель переписать?

В общем я в растерянности.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 28 июл 2012, 15:59 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 12 фев 2012, 01:02
Сообщения: 462
Для начала я бы посмотрел, что находится в массиве.

_________________
kohanaframework.su - обучение фреймворку Kohana


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 28 июл 2012, 16:15 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 24 июл 2012, 18:00
Сообщения: 701
Откуда: Murom, Russia
admin писал(а):
Для начала я бы посмотрел, что находится в массиве.

В массиве находится то, что нужно.

Вид:
Код:
    <pre>
    <?php
      foreach($menu as $key => $val)
        echo var_dump($val);
    ?>
    </pre>


Вывод:
Код:
array(4) {
  'ID' =>
  string(1) "1"
  'PARENT' =>
  string(1) "0"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(12) "Одежда"
}
array(4) {
  'ID' =>
  string(1) "2"
  'PARENT' =>
  string(1) "0"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(10) "Сумки"
}
array(4) {
  'ID' =>
  string(1) "3"
  'PARENT' =>
  string(1) "0"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(10) "Обувь"
}
array(4) {
  'ID' =>
  string(1) "4"
  'PARENT' =>
  string(1) "0"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(20) "Аксессуары"
}
array(4) {
  'ID' =>
  string(1) "5"
  'PARENT' =>
  string(1) "1"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(12) "Жакеты"
}
array(4) {
  'ID' =>
  string(1) "6"
  'PARENT' =>
  string(1) "1"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(12) "Жилеты"
}
array(4) {
  'ID' =>
  string(1) "7"
  'PARENT' =>
  string(1) "1"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(12) "Куртки"
}
array(4) {
  'ID' =>
  string(1) "8"
  'PARENT' =>
  string(1) "1"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(16) "Футболки"
}
array(4) {
  'ID' =>
  string(2) "12"
  'PARENT' =>
  string(1) "2"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(25) "Большие сумки"
}
array(4) {
  'ID' =>
  string(2) "13"
  'PARENT' =>
  string(1) "2"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(27) "Дорожные сумки"
}
array(4) {
  'ID' =>
  string(2) "14"
  'PARENT' =>
  string(1) "2"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(37) "Дорожные косметички"
}
array(4) {
  'ID' =>
  string(2) "15"
  'PARENT' =>
  string(1) "2"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(14) "Рюкзаки"
}
array(4) {
  'ID' =>
  string(2) "16"
  'PARENT' =>
  string(1) "2"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(16) "Портфели"
}
array(4) {
  'ID' =>
  string(2) "21"
  'PARENT' =>
  string(1) "3"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(14) "Ботинки"
}
array(4) {
  'ID' =>
  string(2) "22"
  'PARENT' =>
  string(1) "3"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(18) "Кроссовки"
}
array(4) {
  'ID' =>
  string(2) "23"
  'PARENT' =>
  string(1) "3"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(12) "Лоферы"
}
array(4) {
  'ID' =>
  string(2) "24"
  'PARENT' =>
  string(1) "3"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(14) "Сандали"
}
array(4) {
  'ID' =>
  string(2) "25"
  'PARENT' =>
  string(1) "3"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(12) "Сапоги"
}
array(4) {
  'ID' =>
  string(2) "29"
  'PARENT' =>
  string(1) "4"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(14) "Брелоки"
}
array(4) {
  'ID' =>
  string(2) "30"
  'PARENT' =>
  string(1) "4"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(14) "Гаджеты"
}
array(4) {
  'ID' =>
  string(2) "31"
  'PARENT' =>
  string(1) "4"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(16) "Галстуки"
}
array(4) {
  'ID' =>
  string(2) "32"
  'PARENT' =>
  string(1) "4"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(16) "Кошельки"
}
array(4) {
  'ID' =>
  string(2) "33"
  'PARENT' =>
  string(1) "4"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(10) "Ремни"
}
array(4) {
  'ID' =>
  string(2) "34"
  'PARENT' =>
  string(1) "4"
  'SEX' =>
  string(3) "man"
  'CATEGORY' =>
  string(27) "Головные уборы"
}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 28 июл 2012, 18:04 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 12 фев 2012, 01:02
Сообщения: 462
Мне массив нужен был, чтобы себе скопировать и у себя посмотреть :)
Ну все верно..у вас перебирает категории, потом подкатегории.
Код:
if($items_val['PARENT'] == 0)


не срабатывает, но
Код:
echo '<li><ul>'."\n";

выводится все равно.

Попробуйте
Код:
  <div id="menu">
    <ul>
    <?php
      foreach($menu as $items_id => $items_val)
        // Если этого не сделать и пройтись форичем прямо по $items_val получается фигня какая-то
        $newmenu[] = $items_val;
      foreach($newmenu as $items_id => $items_val)
      {
        if($items_val['PARENT'] == 0)
{
          echo '<li>' . HTML::anchor('#', $items_val['CATEGORY']) . '</li>'."\n";
        echo '<li><ul>'."\n";
        foreach($newmenu as $p_items_val)
        {
          if($p_items_val['PARENT'] == $items_val['ID'])
            echo '<li>' . HTML::anchor(URL::site($items_val['SEX']) .'/category/' . $p_items_val['ID'], $p_items_val['CATEGORY']) . '</li>' ."\n";
        }
        echo '</ul></li>'."\n";
}
      }
    ?>
    </ul>
  </div>


_________________
kohanaframework.su - обучение фреймворку Kohana


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 28 июл 2012, 18:11 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 24 июл 2012, 18:00
Сообщения: 701
Откуда: Murom, Russia
admin писал(а):
Попробуйте ...


Эврика!
Спасибо, добавление фигурных скобок сделало свою работу!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 28 июл 2012, 23:49 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 24 июл 2012, 18:00
Сообщения: 701
Откуда: Murom, Russia
Тема закрыта. Спасибо администратору.

Жалко нет кнопки "Закрыть тему".
Скорее бы админ нашёл время и пересадил сайт и форум на Кохану и дополнил форум нужной функциональностью.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 12 авг 2012, 01:53 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 12 фев 2012, 01:02
Сообщения: 462
Тэкс. Вот и пригодилась незакрытая тема :P
Тоже стал делать иерархическое меню, только уровень вложенности может быть любым, ну как на блоге с основным сайтом. Что-то такое и получилось. Сделал так:
Код:
                        <?php
   
                            function generate_menu($cat_menu, $level)
                            {
                                foreach($cat_menu[$level] as $id => $category)
                                {
         echo '<li>'. HTML::anchor($category['alt_name'], $category['name'], array('title' => $category['name'])) . '</li>'."\n";

         if(isset($cat_menu[$id]))
         {
             echo '<li><ul>'."\n";
             generate_menu($cat_menu, $id);
             echo '</ul></li>'."\n";
         }
                                }
                            }
   
                            $cat_menu = array();
                            foreach($categories as $category)
                            {
                                $id = $category->id;
                                $cat_menu[$category->parent_id][$id]['name'] = $category->name;
                                $cat_menu[$category->parent_id][$id]['alt_name'] = $category->alt_name;
                            }
   
                            generate_menu($cat_menu, 0);
                        ?>


Что не нравится - слишком много кода в представлении. Впрочем функцию можно куда-нибудь вынести.

_________________
kohanaframework.su - обучение фреймворку Kohana


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 12 авг 2012, 11:38 
Не в сети
Бывалый
Аватара пользователя

Зарегистрирован: 05 июн 2012, 03:08
Сообщения: 213
Может здесь подсмотреть? )
http://www.tommylacroix.com/2008/09/10/ ... ng-a-tree/

_________________
http://de-en.info (работает на Kohana 3.3)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 12 авг 2012, 12:00 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 24 июл 2012, 18:00
Сообщения: 701
Откуда: Murom, Russia
admin писал(а):
Тоже стал делать иерархическое меню, только уровень вложенности может быть любым, ну как на блоге с основным сайтом. Что-то такое и получилось. Сделал так:


Я кстати тоже слегка переделал:

Controller:
Код:
...

$gender = $this->request->param('gender');
$sex = ORM::factory('sex', array('name' => $gender));
$tree = $sex->categories->find_all()->as_array();

...

      $content = View::factory('/shop/category')
               ->bind('menu', $tree)
               ...
               ->bind('gender', $gender);
...



View:
Код:
<ul>
   <?php
   foreach ($menu as $item)
   {
      if ($item->parent_id == 0)
      {
         echo '<li class="category-title">' . $item->category . '</li>';
         echo '<li class="category-content"><ul>';
         foreach ($menu as $parent_item)
         {
            if ($parent_item->parent_id == $item->id)
               echo '<li>' . HTML::anchor(URL::site($gender . '/category/' . $parent_item->id), $parent_item->category) . '</li>';
         }
         echo '</ul></li>';
      }
   }
   ?>
</ul>



admin писал(а):
Что не нравится - слишком много кода в представлении. Впрочем функцию можно куда-нибудь вынести.


Такое же ощущение...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Иерархическое меню
СообщениеДобавлено: 12 авг 2012, 12:08 
Не в сети
Администратор
Аватара пользователя

Зарегистрирован: 24 июл 2012, 18:00
Сообщения: 701
Откуда: Murom, Russia
AmberLEX писал(а):
Может здесь подсмотреть? )
http://www.tommylacroix.com/2008/09/10/ ... ng-a-tree/


Интересная фиговина :)


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 12 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 4 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Все о фреймворке Kohana  | 
Powered by phpBB® Forum Software © phpBB Group