Jak zdobyć Itemid przez URL i przekazać go do JRoute

14

Mam element menu dla konkretnego widoku w komponencie niestandardowym. Załączony do tego elementu menu mam inny Template Stylewybrany, a nie standardowy szablon. Dostęp do widoku za pomocą menu działa dobrze, ponieważ jest on dołączany do adresu URL Itemid.

Teraz chcę połączyć, używając JRoute, widok z innym, jednak JRoute nie generuje pożądanego adresu URL.

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

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

JRoute nie dołącza Itemid do adresu URL, co powoduje, że wybrany styl szablonu elementu menu nie działa.

Czy istnieje sposób na „obliczenie” Itemid (oprócz wykonania zapytania w tabeli jos_menuw kolumnie link) i dołączenie go do JRoute?

Valentin Despa
źródło
jeśli znasz itemid niż to, raportowanie i Itemid = 123. Nie polecam tej procedury, ponieważ niestandardowy komponent powinien to zrobić automatycznie, jeśli jest już opublikowany.
Dan

Odpowiedzi:

20

Oto technika, której użyłem (nie pamiętam, gdzie ją znalazłem).

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

To działało dla mnie cuda.

Jordan Ramstad
źródło
4

wyjście z JRoute będzie zależeć od tego, co go karmisz.

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

może zwrócić coś innego niż

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

W rzeczywistości, jeśli masz wpis na blogu kategorii pozycji menu dla catid = 5, ten ostatni może dać ci adres URL menu (nie przetestowałem tego dokładnego adresu URL). Spróbuj użyć różnych parametrów get, aby uzyskać różne wyniki (czasami bardzo źle, jak powiedział @Fedik)

jonasfh
źródło
3

Kluczem tutaj jest skonfigurowanie pliku router.php komponentów (który powinien znajdować się w folderze głównym komponentu na froncie) z logiką, która wyszuka i wybierze odpowiedni element menu. Chciałbym zobaczyć, jak to się dzieje automatycznie, ale o ile wiem, tak nie jest.

Prawdopodobnie najlepiej byłoby zastosować ten blok kodu w funkcji pomocniczej, której można użyć do automatycznego znalezienia najlepiej dopasowanego elementu menu dla treści.

Oto kod, którego użyłem w kilku moich niestandardowych komponentach, aby uzyskać najlepiej pasujący element 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();
    }
}

Wszystko to jest trochę bałaganu (i chciałbym ulepszeń, jeśli ktoś je ma!), Ale wykonuje zadanie. Jeśli bieżący element menu jest najlepiej dopasowany, zawsze będzie się go trzymał.

W przeciwnym razie powinien znaleźć najlepsze dopasowanie na podstawie nazwy komponentu -> nazwa widoku -> nazwa układu -> wartość identyfikatora. Im bardziej pasuje do prawej, tym lepiej uważam dopasowanie!

David Fritsch
źródło
2

Afaik JRoute weźmie aktywny Itemid(a także aktywny option), jeśli nie zostanie podany. Jeśli to nie zadziała, oznacza to, że wywołanie twojego kodu przychodzi bez Itemid na początek. Jeśli tak, najłatwiej byłoby dodać Itemid do wywołania początkowego.

Jeśli potrzebujesz wyszukać element menu, nie zrobiłbym bezpośredniego zapytania, ale zamiast tego użyłbym JMenu.

Bakual
źródło
Zauważyłem, że w niektórych przypadkach JRouter może zwrócić zwariowany adres URL, jeśli spróbujesz podać własny identyfikator przedmiotu, przykład dla JRoute::_('index.php?option=com_example&view=reporting&Itemid=10')JRouter może zwrócić /current-path?view=reporting&Itemid=10... czy są jakieś konkretne rzeczy?
Fedik