Как получить Itemid по URL и передать его JRoute

14

У меня есть пункт меню для конкретного представления в пользовательском компоненте. Прикрепленный к этому пункту меню у меня есть другой Template Styleвыбранный, а не стандартный шаблон. Доступ к представлению через меню работает хорошо, так как он прикрепляется к URL Itemid.

Теперь я хочу связать, используя JRoute, представление с другим, однако JRoute не генерирует желаемый URL.

echo JRoute::_('index.php?option=com_example&view=reporting');

/index.php?option=com_example&view=reporting

JRoute не добавит Itemid к URL, из-за чего выбранный стиль шаблона для пункта меню не будет работать.

Есть ли способ «вычислить» Itemid (кроме выполнения запроса в таблице jos_menuпо столбцу link) и прикрепить его к JRoute?

Валентин Деспа
источник
если вы знаете itemid, чем делать, сообщая & Itemid = 123. Я не советую эту процедуру, поскольку ваш пользовательский компонент должен делать это автоматически, если он уже опубликован.
Дан

Ответы:

20

Вот техника, которую я использовал (не могу вспомнить, где я ее нашел).

$app = JFactory::getApplication(); 
$menu = $app->getMenu();
$menuItem = $menu->getItems( 'link', 'index.php?option=com_example&view=reporting', true );
echo JRoute::_('index.php?Itemid='.$menuItem->id);

Это творило чудеса для меня.

Джордан Рамстад
источник
4

вывод JRoute будет зависеть от того, что вы его кормите.

JRoute::_("index.php?option=com_content&view=article&id=10"); 

может вернуть что-то еще, чем

JRoute::_("index.php?option=com_content&view=article&id=10&catid=5"); 

На самом деле, если у вас есть список пунктов меню в блоге для catid = 5, последний может дать вам URL-адрес меню (я не проверял этот точный URL-адрес). Попробуйте использовать разные get-параметры, чтобы получить разные результаты (иногда очень неправильно, как сказал @Fedik)

jonasfh
источник
3

Ключевым моментом здесь является настройка файла вашего компонента router.php (который должен быть найден в корневой папке вашего компонента на внешнем интерфейсе) с логикой, которая будет искать и выбирать соответствующий пункт меню. Я бы хотел, чтобы это произошло автоматически, но, насколько я знаю, это не так.

Вероятно, было бы лучше использовать этот блок кода для некоторой вспомогательной функции, которая может использоваться для автоматического поиска наиболее подходящего пункта меню для содержимого.

Вот код, который я использовал в нескольких моих пользовательских компонентах, чтобы получить наиболее подходящий элемент меню:

// I use this first empty array to avoid having unset properties in my query
$base_array = array('Itemid'=>'', 'option'=>'', 'view'=>'', 'layout'=>'', 'id'=>'');

$app =& JFactory::getApplication();
$menu       = $app->getMenu();
$active = $menu->getActive();

// hack to protect the actual current item as well as the search module or other places that use JRoute::_('index.php');
if (count($query)==2 && isset($query['option']) && isset($query['Itemid']) && $query['option'] && $query['Itemid']) {
    return $segments;
}

// start with no match found
$match = false;
$match_level = 0;

$query += $base_array;

// we want to find a menu item for this if possible. If the active menu item is the current menu item then we should see if there is a better match.
if (empty($query['Itemid']) || ($query['Itemid'] == $active->id && empty($query['task']))) {
    // load all menu items
    $items = $menu->getMenu();

    // use the current item over others if it ties for the best match
    if ($active->query['option'] == $query['option']) {
        $match_level = 1;
        $match = $active;
        if ($active->query['view'] == $query['view']) {
            $match_level = 2;
            if ($active->query['layout'] == $query['layout'] || ($query['layout']=='default' && !$active->query['layout'])) {
                $match_level = 3;
                if ($active->query['id'] == $query['id']) {
                    $match_level = 4;
                }
            }
        }
    }

    // loop through each menu item in order
    foreach ($items as $item) {
        $item->query += $base_array;
        // base check is that it is for this component
        // then cycle through each possibility finding it's match level
        if ($item->query['option'] == $query['option']) {
            $item_match = 1;
            if ($item->query['view'] == $query['view']) {
                $item_match = 2;
                if (!$query['layout'] && $item->query['layout']) {
                    $query['layout'] = 'default';
                }
                if ($item->query['layout'] == $query['layout'] || ($query['layout']=='default' && !$item->query['layout'])) {
                    $item_match = 3;
                    if ($item->query['id'] == $query['id']) {
                        $item_match = 4;
                    }
                }
            }
        }

        // if this item is a better match than our current match, set it as the best match
        if ($item_match > $match_level) {
            $match = $item;
            $match_level = $item_match;
        }

    }

    // if there is a match update Itemid to match that menu item
    if ($match) {
        $query['Itemid'] = $match->id;
        $menuItem = $menu->getItem($match->id);
    } else {
        $menuItem = $menu->getActive();
    }
}

Все это в некотором роде беспорядок (и я хотел бы, чтобы улучшения были у кого-нибудь!), Но это сделано. Если текущий пункт меню является наиболее подходящим, он всегда будет придерживаться этого.

В противном случае он должен найти наилучшее совпадение на основе имени компонента -> имя представления -> имя макета -> значение идентификатора. Чем дальше справа, тем лучше я считаю матч!

Дэвид Фрич
источник
2

Afaik JRoute возьмет активное Itemid(и также активное option), если ничего не предоставлено. Если это не сработает, это означает, что вызов вашего кода начинается без Itemid. Если это так, проще всего было бы добавить Itemid к первоначальному вызову.

Если вам нужно поискать пункт меню, я бы не делал прямой запрос, а использовал бы вместо этого JMenu.

Bakual
источник
Я заметил, что в некоторых случаях JRouter может вернуть какой-то сумасшедший URL, если попытаться предоставить собственный Itemid, пример для JRoute::_('index.php?option=com_example&view=reporting&Itemid=10')JRouter может вернуть /current-path?view=reporting&Itemid=10... есть ли какие-то конкретные вещи?
Федик