Cómo obtener Itemid por URL y pasarlo a JRoute

14

Tengo un elemento de menú para una vista específica en un componente personalizado. Adjunto a este elemento del menú tengo otro Template Styleseleccionado, no la plantilla estándar. Acceder a la vista a través del menú funciona bien, ya que se adjunta a la URL Itemid.

Ahora quiero vincular, usando JRoute, una vista con otra, sin embargo, JRoute no está generando la URL deseada.

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

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

JRoute no agregará el Itemid a la URL, haciendo que el estilo de plantilla seleccionado para el elemento del menú no funcione.

¿Hay alguna manera de "calcular" el Itemid (además de hacer una consulta en la tabla jos_menude la columna link) y adjuntarlo a JRoute?

Valentin Despa
fuente
si conoce el itemid que hacer, informes y Itemid = 123. No recomiendo este procedimiento ya que su componente personalizado debería hacerlo automáticamente si ya está publicado.
Dan

Respuestas:

20

Aquí hay una técnica que utilicé (no recuerdo dónde la encontré).

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

Esto ha funcionado de maravilla para mí.

Jordan Ramstad
fuente
4

la salida de JRoute dependerá de lo que alimente.

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

podría devolver algo más que

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

De hecho, si tiene una lista de blog de categoría de elemento de menú para catid = 5, este último puede proporcionarle la url de menú (no he probado esta url exacta). Pruebe con diferentes parámetros get para obtener resultados diferentes (a veces muy incorrectos, como dijo @Fedik)

jonasfh
fuente
3

La clave aquí es configurar el archivo router.php de sus componentes (que debe encontrarse en la carpeta raíz de su componente en la parte frontal) con una lógica que buscará y seleccionará el elemento de menú apropiado. Me encantaría ver que esto suceda automáticamente, pero que yo sepa, este no es el caso.

Probablemente sería mejor trabajar este bloque de código en algún tipo de función auxiliar que pueda usarse para encontrar automáticamente el elemento de menú que mejor se ajuste al contenido.

Aquí está el código que he usado en varios de mis componentes personalizados para obtener el elemento de menú que mejor se ajusta:

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

Todo esto es un desastre (¡y me encantaría las mejoras si alguien las tiene!), Pero hace el trabajo. Si el elemento del menú actual es la mejor coincidencia, siempre se mantendrá con eso.

De lo contrario, debería encontrar la mejor coincidencia según el nombre del componente -> nombre de la vista -> nombre del diseño -> valor de id. ¡Cuanto más a la derecha coincida, mejor lo consideraré!

David Fritsch
fuente
2

Afaik JRoute tomará el activo Itemid(y también el activo option) si no se proporciona ninguno. Si eso no funciona, significa que la llamada a su código viene sin Itemid para empezar. Si es así, lo más fácil sería agregar el Itemid a la llamada inicial.

Si necesita buscar el elemento del menú, no haría una consulta directa, sino que usaría JMenu.

Bakual
fuente
Me di cuenta de que en algunos casos JRouter puede devolver alguna URL loca, si intenta proporcionar su propio Itemid, el ejemplo de JRoute::_('index.php?option=com_example&view=reporting&Itemid=10')JRouter puede devolver /current-path?view=reporting&Itemid=10... ¿hay algunas cosas específicas?
Fedik