@dzandut

PHP при переборе массива разнести его на несколько областей?

Делаю шаблон для Joomla 4. Сам шаблон уже сверстан и реализован большой функционал на JS.
Моя задача сделать из него шаблон для этой CMS

Описание задачи:
Реализовать меню шабона на CMS
В joomla это делается через модуль mod_menu. И реализовано это через foreach.
Шаблон имеет 3 разынх вида меню. И для так сказать тепичной части этого меню проблем не было.
А вот одна часть меню реализована на JS и проблему создает его структура.
Оно имеет следующий вид:
<ul>
    <li id="to-tab1">Родительский пункт меню1</li>
    <li id="to-tab2">Родительский пункт меню2</li>
    <li id="to-tab3">Родительский пункт меню3</li>
</ul>
<div>
    <div id="tab1">
        <ul>
            <li>Наследник родительского пункта меню 1</li>
            <li>Наследник родительского пункта меню 1</li>
            <li>Наследник родительского пункта меню 1</li>
        </ul>
    </div>
    <div id="tab2">
        <ul>
            <li>Наследник родительского пункта меню 2</li>
            <li>Наследник родительского пункта меню 2</li>
            <li>Наследник родительского пункта меню 2</li>
        </ul>
    </div>
</div>

Для меня сложность как раскидать пункты меню в 2 разные зоны при этом сохранить их порядок.

Дополнительно попробую описать ситуацию без привязки к CMS
Есть массив следующего вида:
0 =>Сложное меню
1 => Родитель 1
2 => Дочерний 1.1
3 => Дочерний 1.2
4 => Родитель 2
5 => Дочерний 2.1
6 => Дочерний 2.2
7 => Родитель 3
8 => Дочерний 3.1
нужно вывести:
<ul>
    <li id="Проблемный участок">
        Сложное меню(Это пункт)
        <ul>
            Родитель 1
            Родитель 2
        </ul>
        <div>
            Дочерний 1.1
            Дочерний 1.2
        </div>
        <div>
            Дочерний 2.1
            Дочерний 2.2
        </div>
    </li>
    <li id="Реализовання часть">
        Родитель 3
        <ul>
            <li>Дочерний 3.1</li>
        </ul>
    </li>
</ul>
  • Вопрос задан
  • 124 просмотра
Пригласить эксперта
Ответы на вопрос 1
sergeytolkachyov
@sergeytolkachyov
https://web-tolk.ru
Там придется заморочиться немного. У меня в магазине 2 меню:
  • одно - каталог товаров, где родительский пункт меню - один - "каталог"
  • второе - обычное меню с контактами, доставками и т.д.

Вот для меню-каталога я сделал свой макет вывода mod_menu. В modules/mod_menu/tmpl есть 5 файлов:
  1. default.php - сам цикл по массиву с пунктами
  2. default_component.php - layout для вывода ссылки на компонент
  3. default_heading.php - заголовок
  4. default_separator.php - разделитель
  5. default_url.php - внешняя ссылка

Все это дело копируем в ту же папку и заменяем в названии файлов "default" на что-то свое - catalog.php, catalog_component.php и т.д. В основном файле с циклом нужно имена лейаутов в switch-case подправить тоже на "catalog".

В настройках модуля есть параметр "начальный уровень". Скрины для тройки, но в четверке то же самое должно быть.
61f0c71d674c5467287356.png
61f0c72b67ac9009266415.png
У каждого элемента объекта с пунктами меню есть parent_id.
$item->deeper - флаг, означающий, что есть вложенные пункты меню.
$item->shallower означает, что это последний пункт меню (вообще в меню в целом) и можно ставить закрывающие теги.
Нам нужно разделить меню на левую часть и правую часть. В пункты меню нужно вставить атрибуты ссылкам со всякими айдишниками, чтобы на js обрабатывать ховеры мышки. Это делается уже в файлах лейаутов.
Вот код по нему может будет понятно.
Catalog.php
<?php
/**
 * @package     Joomla.Site
 * @subpackage  mod_menu
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Helper\ModuleHelper;

$id = '';

if ($tagId = $params->get('tag_id', ''))
{
	$id = ' id="' . $tagId . '"';
}

$main_menu = '<ul class="nav menu '.$class_sfx . ' mod-list'.$id.'">';

$sub_menus = '';
$sub_menu = '';

// The menu class is deprecated. Use nav instead
?>

	<?php foreach ($list as $i => &$item)
	{
		//если пункт меню верхнего уровня (из настроек)
		if($params->get('startLevel', '') == $item->level){
			$class = 'item-' . $item->id;

			if ($item->id == $default_id)
			{
				$class .= ' default';
			}

			if ($item->id == $active_id || ($item->type === 'alias' && $item->params->get('aliasoptions') == $active_id))
			{
				$class .= ' current';
			}

			if (in_array($item->id, $path))
			{
				$class .= ' active';
			}
			elseif ($item->type === 'alias')
			{
				$aliasToId = $item->params->get('aliasoptions');

				if (count($path) > 0 && $aliasToId == $path[count($path) - 1])
				{
					$class .= ' active';
				}
				elseif (in_array($aliasToId, $path))
				{
					$class .= ' alias-parent-active';
				}
			}

			if ($item->type === 'separator')
			{
				$class .= ' divider';
			}

			if ($item->deeper)
			{
				$class .= ' deeper';
			}

			if ($item->parent)
			{
				$class .= ' parent';
			}

			$main_menu .= '<li class="nav-item d-flex ' . $class . '" data-target-id="'.$item->id.'">';

			switch ($item->type) :
				case 'separator':
				case 'component':
				case 'heading':
				case 'url':
					require ModuleHelper::getLayoutPath('mod_menu', 'catalog_' . $item->type);
					break;

				default:
					require ModuleHelper::getLayoutPath('mod_menu', 'catalog_url');
					break;
			endswitch;

				if ($item->deeper)
				{
					$sub_menu .= '<ul class="nav tab-pane fade'.$id.'" role="tabpanel" id="catalog-submenu-'.$item->id.'">';
				}
				elseif ($item->shallower)
				{
					$sub_menu .= '</ul>';
				}
				$main_menu .= '</li>';


		} else {
			$class = 'item-' . $item->id;

			if ($item->id == $default_id)
			{
				$class .= ' default';
			}

			if ($item->id == $active_id || ($item->type === 'alias' && $item->params->get('aliasoptions') == $active_id))
			{
				$class .= ' current';
			}

			if (in_array($item->id, $path))
			{
				$class .= ' active';
			}
			elseif ($item->type === 'alias')
			{
				$aliasToId = $item->params->get('aliasoptions');

				if (count($path) > 0 && $aliasToId == $path[count($path) - 1])
				{
					$class .= ' active';
				}
				elseif (in_array($aliasToId, $path))
				{
					$class .= ' alias-parent-active';
				}
			}

			if ($item->type === 'separator')
			{
				$class .= ' divider';
			}

			if ($item->deeper)
			{
				$class .= ' deeper';
			}

			if ($item->parent)
			{
				$class .= ' parent';
			}

			$sub_menu .= '<li class="' . $class . '">';

			switch ($item->type) :
				case 'separator':
				case 'component':
				case 'heading':
				case 'url':
					require ModuleHelper::getLayoutPath('mod_menu', 'catalog_' . $item->type);
					break;

				default:
					require ModuleHelper::getLayoutPath('mod_menu', 'catalog_url');
					break;
			endswitch;

			// The next item is deeper.
			if ($item->deeper)
			{
				$sub_menu .= '<ul class="nav-child unstyled small">';
			}
			// The next item is shallower.
			elseif ($item->shallower)
			{
				$sub_menu .= '</li>';
				$sub_menu .= str_repeat('</ul></li>', $item->level_diff);
			}
			// The next item is on the same level.
			else
			{
				$sub_menu .= '</li>';
			}
		}
	}
	$main_menu .= "</ul>";
	$sub_menu .= "</ul>";

	$sub_menus .= $sub_menu;

	?>
<div class="mainmenu col-12 col-md-4 col-lg-3">
	<?php
		echo $main_menu;
	?>
</div>
<div class="submenu bg-white col-12 d-md-block col-md-8 col-lg-9">
	<div class="tab-content overflow-auto" id="catalog-submenu-tabContent" role="tablist">
		<button class="btn btn-sm btn-outline-secondary d-md-none fas fa-chevron-left my-2" id="submenu-back-btn"><span class="ml-2">Назад</span></button>
		<?php echo $sub_menus;?>
	</div>
</div>


Для примера - catalog_component.php. Этот файл вызывается в предыдущем catalog.php с помощью ModuleHelper::getLayoutPath('mod_menu', 'catalog_' . $item->type); . $item->type там будет содержать название лейаута - component.

<?php
/**
 * @package     Joomla.Site
 * @subpackage  mod_menu
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
 * @license     GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

$attributes = array();

if ($item->anchor_title)
{
	$attributes['title'] = $item->anchor_title;
}
$attributes['class'] .= "nav-link w-100";
if ($item->anchor_css)
{
	$attributes['class'] = $item->anchor_css;
}

if ($item->anchor_rel)
{
	$attributes['rel'] = $item->anchor_rel;
}

$linktype = $item->title;

if ($item->menu_image)
{
	if ($item->menu_image_css)
	{
		$image_attributes['class'] = $item->menu_image_css;
		$linktype = JHtml::_('image', $item->menu_image, $item->title, $image_attributes);
	}
	else
	{
		$linktype = JHtml::_('image', $item->menu_image, $item->title);
	}

	if ($item->params->get('menu_text', 1))
	{
		$linktype .= '<span class="image-title">' . $item->title . '</span>';
	}
}

if ($item->browserNav == 1)
{
	$attributes['target'] = '_blank';
}
elseif ($item->browserNav == 2)
{
	$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes';

	$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
}


//если пункт меню верхнего уровня (из настроек)
if($params->get('startLevel', '') == $item->level){
	$main_menu .= JHtml::_('link', JFilterOutput::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
	if($item->deeper){
		$main_menu .=  '<button class="btn ml-auto d-flex align-items-center mr-lg-2" data-target="catalog-submenu-'.$item->id.'" role="tab" id="child-menu-toggler-'.$item->id.'"><i class="fas fa-chevron-right"></i></button>';
	}

} else {
	$sub_menu .= JHtml::_('link', JFilterOutput::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
}


Попробуйте доковырять под себя. Может поможет.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы