web-dev-qa-db-fra.com

Comment obtenir Itemid par URL et le transmettre à JRoute

J'ai un élément de menu pour une vue spécifique dans un composant personnalisé. Attaché à cet élément de menu, j'ai un autre Template Style Sélectionné, pas le modèle standard. L'accès à la vue via le menu fonctionne bien, car il attache à l'URL le Itemid.

Maintenant, je veux lier, en utilisant JRoute, une vue avec une autre, cependant, JRoute ne génère pas l'URL souhaitée.

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

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

JRoute ne va pas ajouter l'id Itemid à l'URL, ce qui empêche le style de modèle sélectionné pour l'élément de menu de fonctionner.

Y a-t-il un moyen de "calculer" le Itemid (à part faire une requête dans la table jos_menu Sur la colonne link) et l'associer à JRoute?

14
Valentin Despa

Voici une technique que j'ai utilisée (je ne me souviens plus où je l'ai trouvée).

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

Cela a fonctionné à merveille pour moi.

20
Jordan Ramstad

la sortie de JRoute dépendra de ce que vous lui fournissez.

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

pourrait retourner autre chose que

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

En fait, si vous avez une liste de blog de catégorie d’éléments de menu pour catid = 5, cette dernière peut vous donner l’URL du menu (je n’ai pas testé cette URL exacte). Essayez avec différents paramètres get pour obtenir des résultats différents (parfois très faux, comme l'a dit @ Fedik)

4
jonasfh

La clé ici est de configurer le fichier routeur.php de vos composants (qui doit se trouver dans le dossier racine de votre composant au front-end) avec une logique qui recherche et sélectionne l’élément de menu approprié. J'aimerais que cela se produise automatiquement, mais autant que je sache, ce n'est pas le cas.

Il serait probablement préférable d’utiliser ce bloc de code dans un type de fonction d’aide pouvant être utilisé pour trouver automatiquement le meilleur élément de menu pour le contenu.

Voici le code que j'ai utilisé dans plusieurs de mes composants personnalisés pour obtenir le meilleur élément de menu:

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

Tout cela est en quelque sorte un gâchis (et j'aimerais que des améliorations soient apportées si quelqu'un en a!), Mais le travail est fait. Si l'élément de menu actuel correspond le mieux, il s'en tiendra toujours à cela.

Sinon, la meilleure correspondance doit être trouvée en fonction du nom du composant -> nom de la vue -> nom de la présentation -> valeur id. Plus on s'accorde à droite, mieux je considère le match!

3
David Fritsch

Afaik JRoute prendra le Itemid actif (ainsi que le option actif) si aucun n’est fourni. Si cela ne fonctionne pas, cela signifie que l'appel de votre code vient sans Itemid pour commencer. Si tel est le cas, le plus simple serait d’ajouter le Itemid à l’appel initial.

Si vous devez rechercher l'élément de menu, je ne ferais pas de requête directe mais utiliserais plutôt JMenu.

2
Bakual