--=REKLAMA=--

Obsługa prostych adresów w Twoim komponencie

Z Joomla!WikiPL

Wersja Komodore (dyskusja | edycje) z dnia 01:29, 19 kwi 2014

(różn.) ← poprzednia wersja | przejdź do aktualnej wersji (różn.) | następna wersja → (różn.)

Wstęp

Proste adresy internetowe nazywane też czytelnymi dla człowieka (human-readable), czystymi albo przyjaznymi dla wyszukiwarek (Search Engine Friendly, SEF) to adresy URL, które mają sens zarówno dla ludzi, jak i wyszukiwarek, ponieważ objaśniają ścieżki do stron, na które wskazują. Człowiek może je łatwo zapisać, zapamiętać i przeczytać, a robot wyszukiwarki zidentyfikować na ich podstawie strukturę witryny i prawidłowo ją zaindeksować.

Od wersji 1.5, Joomla! jest zdolny do tworzenia i przetwarzania adresów URL w dowolnym formacie, w tym adresów przyjaznych dla wyszukiwarek. Funkcja ta nie jest zależna od translacji (przepisywania) URL przez serwer WWW, działa, nawet jeśli Joomla jest zainstalowany na innym serwerze niż Apache z modułem mod_rewrite. Proste adresy tworzone są według ustalonego wzorca, ale użytkownik może sam zdefiniować krótki tekst opisowy (alias) dla każdego segmentu adresu URL.

Wewnętrzna, lokalna część prostego adresu URL (część po nazwie domeny) nazywa się trasą (route. Dlatego tworzenie i przetwarzanie adresów SEF nazywane jest dalej trasowaniem (routing), a odpowiedni kod nazywany jest ruterem (router).

W Joomla! każdy komponent jest odpowiedzialny za obsługę własnych adresów SEF. Dlatego też, jako twórca komponentu, będziesz musiał stworzyć własny router, aby umożliwić komponentowi używanie adresów SEF.

Koncepcja

Zakładając, że stosujesz standardowe praktyki rozwoju, Twój komponent używa prawdopodobnie systemowe adresy URL, które wyglądają trochę jak http://www.example.com/index.php?option=com_twójkomponent&view=article&id=1&catid=20&Itemid=50, i twoim celem jest przekształcenie tego adresu do http://www.example.com/example-menu-item/20/1. Jako deweloper, masz dwa zadania: poinformować system, że niektóre fragmenty tekstu są adresami i muszą zostać przekształcone oraz objaśnić systemowi, jak je przekształcić i używać.

Stosowanie JRoute::_

Trudne i nieefektywne jest dla Joomla! dowiadywanie się, które części Twojego komponentu generują URL. Do wspierania adresów SEF, trzeba będzie zmienić kod generowania adresu URL tak, że stosuje JRoute::_ przed wyprowadzeniem adresu URL:

echo JRoute::_('index.php?view=article&id=1&catid=20');

Zauważ, że jest to możliwe, aby pominięcie parametrów opcji i Itemid. Opcja domyślnie składa się z nazwy komponentu aktualnie wykonywanego i Itemid domyślnych dla bieżącego ID pozycji menu.

W ogóle, to należy stosować tylko do adresów URL, które użytkownicy i/lub wyszukiwarki są w stanie zobaczyć. Na przykład, nie ma potrzeby przekształcenia adresów stosowanych w przekierowaniach, które bezpośrednio prowadzą do innych przekierowań.

Jeśli użytkownik wyłączy adresy SEF w ustawieniach witryny, JRoute::_ będzie używać adresy nie-SEF bez żadnych zmian w kodzie.

Pisanie rutera

Trzeba także napisać ruter, którym jest jeden plik z dwoma funkcjami, które przekształcają używane przez system URL-e do i z adresów SEF. Plik ten musi być umieszczony w /components/com_twójkomponent/router.php .

Pierwsza funkcja [NazwaKomponentu]BuildRoute(&$zapytanie) musi przekształcić tablicę parametrów URL do tablicy segmentów, które będą stanowić URL SEF. Schematycznie przemiana przebiega w następujący sposób :

http://www.example.com/index.php?option=com_yourcomponent&view=article&id=1&catid=20&Itemid=50
JRoute::_ dołączany przez Twój komponent lub inne rozszerzenie
$zapytanie=array('view'=>'article','id'=>1,'catid'=>20)
ruter com_TwójKomponentBuildRoute
$segmenty=array(20,1)
budowanie trasowania wewnątrzn Joomla (do wyświetlenia)
http://www.example.com/example-menu-item/20/1

Druga funkcja [NazwaKomponentu]ParseRoute($segmenty) musi przekształcić tablicę segmentów z powrotem do tablicy parametrów URL. Schematycznie:

http://www.example.com/example-menu-item/20/1
parsowanie trasowania wewnątrzna Joomla
$segmenty=array(20,1)
rutera com_twójkomponentParseRoute
$zapytanie=array('view'=>'article','id'=>1,'catid'=>20)

Obie funkcje muszą współpracować w taki sposób, żeby oryginalny URL mógł być zrekonstruowany. Możesz myśleć o BuildRoute jako formie kodowania a ParseRoute dekodowania. Gdy oryginalny URL nie jest prawidłowo odtwarzany, komponent przestanie działać.

Przygotowanie danych dla trasowania

Alias ​​

Pierwszym etapem jest wygenerowanie tak zwanego aliasu. Alias ​​jest używany w adresie URL zamiast tytułu. Jest to tekst, który chcesz mieć w adresie URL. Alias musi być bezpiecznym ​​URI, co oznacza, że akcentowane znaki UTF8, są zastąpione przez ich odpowiedniki ASCII7, a białe znaki myślnikami itp.

Alias ​​może być zdefiniowany przez użytkownika, ale należy upewnić się, że powyższe wymagania dotyczące bezpiecznego aliasowego URL są spełnione. Dobrym sposobem na to jest w użycie JTable::check() w trakcie procesu zapisywania.

Spójrz na przykładowy kod:

function check()
{
    jimport( 'joomla.filter.output' );
    if(empty($this->alias)) {
	    $this->alias = $this->title;
    }
    $this->alias = JFilterOutput::stringURLSafe($this->alias);
 
    / * Wszystkie inne Twoje kontrole * /
    return true;
}

Jeśli pole alias jest puste, tytuł będzie używany jako alias. Następnie alias zostanie przetworzony na bezpieczny URL za pomocą JFilterOutput::stringURLSafe().

Slug

Kontynuując powyższy przykład "slug" - "1:Zapraszamy do joomla" ma dwie części. Pierwsza część to identyfikator artykułu (ID), a druga to alias. Są one oddzielone od siebie dwukropkiem. Te dwa elementy zostały połączone w zapytaniu do bazy danych w modelu:

$query = 'SELECT a.*, '.
         'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(":", a.id, a.alias) ELSE a.id END as slug,'
         /*...*/;

Po tym etapie slug jest używany zamiast id.

Trasowanie URL

JRoute::_ - wewnętrzna metoda translacji URL Joomla! na URL użytkownika. JRoute posiada trzy parametry i jej prototypem jest:

JRoute::_($url,$xhtml=true,$ssl=null);

Gdzie:

  • $url jest typu string zawierającym absolutny lub relatywny wewnętrzny URL Joomla!.
  • $xhtml jest typu boolean i określa, czy wyjście ma być w XHTML. Ten parametr jest opcjonalny i jeśli jest pominięty ma domyślną wartość true.
  • $ssl jest typu integer i określa, czy URI powinno być zabezpieczone. Przyjmuje trzy stany:
    • 1 - aby wymusić bezpieczne URI
    • 0 - wybór w zależności od żądania
    • -1 wymusza niezabezpieczone URI.

Najważniejszym parametrem jest $url. Wywołanie tej metody może wyglądać tak:

JRoute::_( 'index.php?view=article&id='.$row->slug );

$row­>slug jest wartością generowaną w drugim etapie z kombinacji id i aliasu tytułu.

Kolejną zaletą korzystania z JRoute jest to, że ruter obsługuje teraz $option (nazwa komponentu) i $Itemid (ID pozycji menu).Sam komponent nie musi znać swojej nazwy ($option) lub aktywnej pozycji menu ($Itemid), jak to miało miejsce w poprzedniej wersji Joomla!.

Ważne jest, aby pomyśleć o kolejności parametru URL w tym etapie. Będzie to bardziej oczywiste, gdy przyjrzymy się plikowi router.php w następnej sekcji.

Proces budowania JRouter jest podzielony na dwa etapy:

  • Utwórz trasę aplikacji. Trasa aplikacji jest w pełni obsługiwana przez JRouter i komponent dewelopera nie musi nic robić, aby to działało.
  • Utwórz trasę komponentu. Aby utworzyć trasę komponentu, JRouter szuka router.php w katalogu komponentu, który jest odpowiedzialny za budowę trasy dla komponentu.

Ruter komponentu

W pliku router.php będziemy mieć dwie funkcje. Jedna jest odpowiedzialna za budowanie URL, a druga za parsowanie go. W następnym przykładzie zakładamy, że mamy trzy widoki, dwa bardzo proste i jeden bardziej zaawansowany, na które mogą wskazywać odnośniki. Pierwszy jest przeglądem kategorii (view=categories), drugi pojedynczą kategorią (view=category) i trzeci jest pojedyńczym artykułem (view=article).

Plik router.php powinien znajdować się w obszarze frontu strony Twojego komponentu. Nie jest on używany w obszarze administracyjnym/zapleczu strony. Nie zapomnij również dodać go do Twojego pliku XML plik manifestu w folderze frontu strony Twojego komponentu.

Prosty przykład

Poniższy przykład zilustruje podstawową implementację rutera dla Twojego komponentu.

function [componentname]BuildRoute( &$query )
{
       $segments = array();
       if(isset($query['view']))
       {
                $segments[] = $query['view'];
                unset( $query['view'] );
       }
       if(isset($query['id']))
       {
                $segments[] = $query['id'];
                unset( $query['id'] );
       };
       return $segments;
}

JRouter przekazuje tablicę $query do funkcji [NazwaKomponentu]BuildRoute</ code>. Ta funkcja doda odpowiednie części tablicy do tablicy $segments w odpowiedniej kolejności i zwróci odpowiednio uporządkowaną tablicę. Zawartość tablicy <code>$query nie może być ustawiona, inaczej JRouter doda ją do adresu URL w formie łańcucha zapytania (tzn. wszelkie zmienne, które nie są obsługiwane przez ruter będą przekazywane w zapytaniu).

Prefix NazwaKomponentu jest nazwą Twojego komponentu, jaką znaleźć można w katalogu z plikami komponentów. Na przykład, komponent "Magic" w katalogu /components/com_magic/... powinien używać jako przedrostka magic (małymi literami).

Druga funkcja w router.php parsuje adres URL:

function [componentname]ParseRoute( $segments )
{
       $vars = array();
       switch($segments[0])
       {
               case 'categories':
                       $vars['view'] = 'categories';
                       break;
               case 'category':
                       $vars['view'] = 'category';
                       $id = explode( ':', $segments[1] );
                       $vars['id'] = (int) $id[0];
                       break;
               case 'article':
                       $vars['view'] = 'article';
                       $id = explode( ':', $segments[1] );
                       $vars['id'] = (int) $id[0];
                       break;
       }
       return $vars;
}

Co się w niej dzieje? W funkcji [NazwaKomponentu]BuildRoute zorganizowaliśmy pozycje w tablicy $query w określonej kolejności. Oznacza to, że w tym przykładzie w tablicy widok jest pierwszy a identyfikator drugi. Czytając $segments[0], możemy uzyskać dostęp do nazwy widoku. Ustawiamy właściwy widok i/lub identyfikator w zależności od jego wartości i zwracamy tablicę $vars do JRouter. Tablica $vars powinna być tablicą asocjacyjną podobną do tablicy, która została przekazana do metody BuildRoute.

Powyższy przykład z router.php jest bardzo prostym sposobem na generowanie adresów SEF, lecz powinien pokazać, jak to działa dość wyraźnie.

Wygenerowany adres URL w tym przykładzie zawiera nazwę widoku i nie odzwierciedla hierarchii zawartości:

http://www.example.com/[aliasmenu]/[widok]/[slug]

Bardziej zaawansowany przykład

W kolejnym przykładzie spróbujemy pozbyć się konieczności podawania widoku i spróbujemy odzwierciedlić aktualny poziom hierarchii w adresie URL.

Naszym celem są URLe, które wyglądają tak:

  • Podczas przeglądania artykułu: http://www.example.com/[menualias]/[categoria]/[artykuł]
  • Podczas przeglądania kategorii: http://www.example.com/[menualias]/[categoria]
  • Podczas przeglądania przeglądu kategorii: http://www.example.com/[menualias]

Załóżmy, że zrobiliśmy krok 1 i 2 również dla kategorii.

Link do artykułu będzie wyglądać tak:

JRoute::_( 'index.php?view=article&catid='.$row-­>catslug .'&id='.$row-­>slug );

a link do kategorii będzie wyglądać tak:

JRoute::_( 'index.php?view=category&id='.$row->catslug );

Odpowiedni router.php:

function [''NazwaKomponentu'']BuildRoute(&$query)
{
       $segments = array();
       if(isset( $query['catid'] ))
       {
                $segments[] = $query['catid'];
                unset( $query['catid'] );
       };
       if( isset($query['id']) )
       {
                $segments[] = $query['id'];
                unset( $query['id'] );
       };
       unset( $query['view'] );
       return $segments;
}

Różnica jest taka, że teraz nie możemy dodać nazwy widoku do tablicy $segments. Nieustawiamy klucza widoku gdyż w przeciwnym razie JRouter doda go do adresu URL jako część kwerendy. Kolejną nową rzeczą jest tutaj dodatkowy parametr catid, który wstawiamy do tablicy $segments.

function [''NazwaKomponentu'']ParseRoute($segments)
{
       $vars = array();
       $app =& JFactory::getApplication();
       $menu =& $app->getMenu();
       $item =& $menu->getActive();
       // licznik segmentów
       $count = count( $segments );
       //Uchwyt widoku i identyfikatora
       switch( $item->query['view'] )
       {
               case 'categories':
                       if($count == 1) {
                               $vars['view'] = 'category';
                       }
                       if($count == 2) {
                               $vars['view'] = 'article';
                       }
                       $id = explode( ':', $segments[$count-1] );
                       $vars['id'] = (int) $id[0];
                       break;
               case 'category':
                       $id   = explode( ':', $segments[$count-1] );
                       $vars['id']   = (int) $id[0];
                       $vars['view'] = 'article';
                       break;
       }
       return $vars;
}

Widać, że funkcja ParseRoute ma więcej różnych części kodu w porównaniu do poprzedniego przykładu. Powód tego jest prosty. Nie mamy nazwy widoku w tablicy $segments i musimy znaleźć inny sposób, aby ją określić.

Musimy dowiedzieć się, z którego poziomu w hierarchii otrzymujemy element główny. Robimy to, patrząc na widok z nazwą pozycji aktywnego menu:

$item-­>query['view']

Musimy także znać liczbę elementów w tablicy $segments:

$count = count( $segments );

Dzięki tym informacjom możemy prawidłowo ustawić widok dla wszystkich możliwych trzech przypadków:

  • Pozycja menu jest linkiem do widoku kategorii a tablica $segments ma dwa elementy ($catid i $id). W tym przypadku wiemy, że musimy parsować link do artykułu.
  • Pozycja menu jest linkiem do widoku kategorii a tablica $segments ma jeden element ($id). W tym przypadku wiemy, że musimy parsować link do kategorii.
  • Pozycja menu jest linkiem do kategorii. W tym przypadku wiemy, że każdy element w tablicy $segments jest identyfikatorem artykułu.

Wynikiem całego tego kodu jest czysty i czytelny dla człowieka adres URL komponentu.

Rutery i pozycje menu

Ostatnim ważnym etapem tworzenia routera jest zastanowienie się co zrobić z pozycjami menu. Jak wyjaśniono to w Proste adresy internetowe, wyjście routera komponentu jest używane po pierwszym segmencie trasy, którym jest aliasem pozycji menu. Stwarza to trudne pytanie: skąd router i/lub inny kod ma wiedzieć, z której pozycji menu trasować?

Załóżmy na przykład, że komponent generuje wyjście dla bieżącej strony /psy, który wymienia wszystkie psy w systemie. Oczywiście, pozycjami na liście muszą być linki do stron, które wyświetlają więcej szczegółów na temat każdego psa. Co powinien zwrócić URL dla psa o ID 21 i nazwie Fido? Użyć routera, który działa zgodnie z zasadami, które widzieliśmy do tej pory. Trasa, która jest generowana /psy/21-fido, lub z dodatkowym przetworzeniem /psy/fido. Ale może użytkownik utworzył pozycję menu z aliasem mojpiesek, który wyświetla właśnie szczegółowe informacje o tym psie. Jest prawdopodobne, że intencją użytkownika było aby trasować adres URL tej pozycji menu, a pozycja na liście powinna odwoływać się do strony /mojpiesek.

Bardziej ogólnie, gdy budujesz trasę, trzeba będzie znaleźć element menu, który jest najbardziej odpowiedni jako punkt wyjścia do budowy trasy. Termin punktem wyjścia jest zaznaczony, ponieważ reszta trasy zależy od konfiguracji pozycji menu. W naszym przykładzie powyżej, /psy/21-fido jest dopuszczalną trasa, /mojpiesek jest zapewne jeszcze lepszą, ale /mojpiesek/21-fido jest po prostu błędne, ponieważ /mojpiesekjest sam w sobie jest elementem menu, który jest skonfigurowany do wyświetlania informacji o Fido.

Dostępne są różne podejścia do rozwiązania tego problemu. Podstawowe komponenty Joomla! rozdzielają zadania na dwie części: ruter i klasę pomocniczą [NazwaKomponentu]RouteHelper. [NazwaKomponentu]RouteHelper dostarcza metody, które mają pozyskać dane do wyświetlenia na wyjściu modułu, podczas gdy ruter analizuje pozycję menu i wstawia informacje, które są określone w konfiguracji pozycji menu do trasy. Oznacza to, że dołączony kod musi jawnie wywołać metodę pomocnika przed trasowaniem (echo JRoute::_(PsyRouteHelper::getPiesRoute(21))).

Materiały anglojęzyczne

© Ten materiał jest dokładnym albo swobodnym tłumaczeniem artykułu http://docs.joomla.org/Supporting_SEF_URLs_in_your_component udostępnionego na licencji JEDL na witrynie: Joomla! Official Documentation Wiki

Dziękujemy za wkład

» Adam Przybylski [komodore],