Comment obtenir Itemid par URL et le transmettre à JRoute

14

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

Maintenant, je veux lier, en utilisant JRoute, une vue avec une autre, mais 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 n'ajoutera pas l'ID d'article à l'URL, ce qui empêchera le style de modèle sélectionné pour l'élément de menu de fonctionner.

Existe-t-il un moyen de "calculer" l'Itemid (en dehors de faire une requête dans le tableau jos_menude la colonne link) et de le joindre à JRoute?

Valentin Despa
la source
si vous connaissez l'itemid que faire, reporting & Itemid = 123. Je ne conseille pas cette procédure car votre composant personnalisé devrait le faire automatiquement s'il est déjà publié.
Dan

Réponses:

20

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 fait des merveilles pour moi.

Jordan Ramstad
la source
4

la sortie de JRoute dépendra de ce que vous l'alimentez.

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ément de menu pour catid = 5, ce dernier 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)

jonasfh
la source
3

La clé ici est de configurer votre fichier router.php de composants (qui devrait être trouvé dans le dossier racine de votre composant sur le front-end) avec une logique qui recherchera et sélectionnera l'élément de menu approprié. J'adorerais que cela se produise automatiquement, mais pour autant que je sache, ce n'est pas le cas.

Il serait probablement préférable de travailler ce bloc de code dans un certain type de fonction d'aide qui peut être utilisée pour trouver automatiquement l'élément de menu le mieux adapté au contenu.

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

// 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 une sorte de gâchis (et j'aimerais des améliorations si quelqu'un en a!), Mais cela fait le travail. Si l'élément de menu actuel correspond le mieux, il s'en tiendra toujours à cela.

Sinon, il devrait trouver la meilleure correspondance en fonction du nom du composant -> nom de la vue -> nom de la mise en page -> valeur id. Plus elle correspond vers la droite, mieux je considère que la correspondance!

David Fritsch
la source
2

Afaik JRoute prendra l'actif Itemid(et aussi l'actif option) si aucun n'est fourni. Si cela ne fonctionne pas, cela signifie que l'appel à votre code est livré sans Itemid pour commencer. Si c'est le cas, la chose la 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 j'utiliserais plutôt JMenu.

Bakual
la source
J'ai remarqué que dans certains cas, JRouter peut renvoyer une URL folle, si vous essayez de fournir votre propre Itemid, l'exemple pour JRoute::_('index.php?option=com_example&view=reporting&Itemid=10')JRouter peut retourner /current-path?view=reporting&Itemid=10... y a-t-il des choses spécifiques?
Fedik