A
A
Andres2022-01-20 18:30:15
PHP
Andres, 2022-01-20 18:30:15

PHP when iterating over an array split it into multiple areas?

I am making a template for Joomla 4. The template itself has already been laid out and a lot of functionality has been implemented in JS.
My task is to make it a template for this CMS

Description of the task:
Implement the template menu on the CMS
In joomla, this is done through the mod_menu module. And this is implemented through foreach.
The template has 3 different types of menus. And there were no problems for the so-called greenhouse part of this menu.
But one part of the menu is implemented in JS and its structure creates a problem.
It looks like this:

<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>

For me, the difficulty is how to scatter menu items into 2 different zones while maintaining their order.

In addition, I will try to describe the situation without reference to the CMS
There is an array of the following form:
0 => Complex menu
1 => Parent 1
2 => Child 1.1
3 => Child 1.2
4 => Parent 2
5 => Child 2.1
6 => Child 2.2
7 = > Parent 3
8 => Child 3.1
should be output:
<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>

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sergei Tolkachev, 2022-01-26
@sergeytolkachyov

There will have to freeze a little. I have 2 menus in my shop:

  • one - product catalog, where parent menu item - one - "catalog"
  • the second is the usual menu with contacts, deliveries, etc.

Here for the menu-catalog, I made my mod_menu output layout. There are 5 files in modules/mod_menu/tmpl :
  1. default.php - the loop itself through the array with items
  2. default_component.php - layout for displaying a link to the component
  3. default_heading.php - header
  4. default_separator.php - separator
  5. default_url.php - external link

We copy the whole thing to the same folder and replace "default" in the file name with something of our own - catalog.php, catalog_component.php, etc. In the main file with the cycle, you need to correct the layout names in the switch-case to "catalog" too.
In the module settings there is an "initial level" parameter. Screenshots for the three, but the same should be in the four.
61f0c71d674c5467287356.png
61f0c72b67ac9009266415.png
Each element of the object with menu items has a parent_id.
$item->deeper is a flag indicating that there are nested menu items.
$item->shallower means that this is the last menu item (in general, in the menu as a whole) and you can put closing tags.
We need to split the menu into a left side and a right side. In the menu items, you need to insert attributes for links with all sorts of IDs in order to process mouse hovers on js. This is already done in the layout files.
Here is the code for it may be clear.
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>

For example - catalog_component.php . This file is called in the previous catalog.php with ModuleHelper::getLayoutPath('mod_menu', 'catalog_' . $item->type); . $item->type there will contain the name of the layout - 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);
}

Try to tweak it for yourself. It might help.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question