Como obter o Itemid por URL e passá-lo para o JRoute

14

Eu tenho um item de menu para uma exibição específica em um componente personalizado. Anexado a este item de menu, tenho outro Template Styleselecionado, não o modelo padrão. O acesso à visualização por meio do menu funciona bem, pois é anexado à URL Itemid.

Agora eu quero vincular, usando o JRoute, uma visualização com outra, no entanto, o JRoute não está gerando a URL desejada.

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

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

JRoute não anexará o Itemid ao URL, fazendo com que o estilo de modelo selecionado para o item de menu não funcione.

Existe uma maneira de "calcular" o Itemid (além de fazer uma consulta na tabela jos_menuna coluna link) e anexá-lo ao JRoute?

Valentin Despa
fonte
se você conhece o item, então, reportando & Itemid = 123. Não aconselho esse procedimento, pois seu componente personalizado deve fazer isso automaticamente se já estiver publicado.
Dan

Respostas:

20

Aqui está uma técnica que eu usei (não me lembro onde a encontrei).

$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);

Isso fez maravilhas para mim.

Jordan Ramstad
fonte
4

a saída do JRoute dependerá da sua alimentação.

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

pode retornar algo mais do que

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

De fato, se você tiver uma listagem de blog de categoria de item de menu para catid = 5, o último poderá fornecer o URL do menu (não testei esse URL exato). Tente com diferentes parâmetros de obtenção para obter resultados diferentes (às vezes muito errados, como disse o @Fedik)

jonasfh
fonte
3

A chave aqui é configurar o arquivo router.php dos componentes (que deve ser encontrado na pasta raiz do seu componente no front end) com uma lógica que irá procurar e selecionar o item de menu apropriado. Eu adoraria ver isso acontecer automaticamente, mas até onde eu sei, esse não é o caso.

Provavelmente, seria melhor trabalhar esse bloco de código em algum tipo de função auxiliar que possa ser usada para encontrar automaticamente o item de menu mais adequado ao conteúdo.

Aqui está o código que eu usei em vários dos meus componentes personalizados para obter o item de menu mais adequado:

// 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();
    }
}

Tudo isso é uma bagunça (e eu adoraria melhorias se alguém as tiver!), Mas faz o trabalho. Se o item de menu atual for a melhor correspondência, ele sempre permanecerá com isso.

Caso contrário, ele deve encontrar a melhor correspondência com base em Nome do componente -> nome da exibição -> nome do layout -> valor do ID. Quanto mais à direita corresponder, melhor considero a partida!

David Fritsch
fonte
2

O Afaik JRoute assumirá o ativo Itemid(e também o ativo option) se nenhum for fornecido. Se isso não funcionar, significa que a chamada para o seu código vem sem o Itemid, para começar. Nesse caso, o mais fácil seria adicionar o Itemid à chamada inicial.

Se você precisar procurar o item de menu, eu não faria uma consulta direta, mas usaria o JMenu.

Bakual
fonte
Percebi que, em alguns casos, o JRouter pode retornar uma URL maluca, se tentar fornecer o próprio Itemid, o exemplo para o JRoute::_('index.php?option=com_example&view=reporting&Itemid=10')JRouter pode retornar /current-path?view=reporting&Itemid=10... há algumas coisas específicas?
Fedik