Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Routing
Forum PHP.pl > Forum > PHP
szaleq
Witam

Mam wątpliwości odnośnie logiki działania routingu w aplikacji implementującej MVC.
Na wstępie słowo odnośnie mojej implementacji:
Aplikacja składa się z modułów, każdy moduł ma swoje kontrolery widoki i modele. Tak więc router musi zwrócić prócz kontrolera i akcji nazwę modułu (oraz opcjonalnie parametry).

Mój dylemat opiszę na podstawie tras dynamicznych (router obsługuje również trasy statyczne oraz regex). Trasy definiuję podając "ścieżkę" oraz tablicę wartości "domyślnych"
i tak mam np trasę:
  1. $router->setRoute(':module/:controller', array(
  2. 'action' => 'index'
  3. ));

Dla ścieżki np. 'blog/posts' router, stwierdziwszy, że podana ścieżka pasuje do danej trasy, zwróci tablicę: ('module' => 'blog', 'controller' => 'posts', 'action' => 'index').

Jednak gdy zdefiniuję kolejną trasę następująco:
  1. $router->setRoute(':controller/:action', array(
  2. 'module' => ':controller'
  3. ));

pojawia się problem. Gdyby router przypasował daną trasę np do ścieżki 'articles/all', zwróciłby tablicę: ('module' => 'articles', 'controller' => 'articles', 'action' => 'all').

Jednak podana ścieżka ('articles/all') pasuje do obu powyższych tras. Obecnie działający router zwróci więc tablicę na podstawie pierwszej ścieżki: ('module' => 'articles', 'controller' => 'all', 'action' => 'index'). Oczywiście nie istnieje taki kontroller jak 'all' w module 'articles' więc pojawi się błąd 404.

I tu mój dylemat: czy router powinien zwracać tablice przypasowań dla wszystkich pasujących tras? wtedy dispatcher stwierdziwszy, że nie ma kontrolera o nazwie 'all' sięgnąłby po następny wynik i trafił na właściwy kontroler.
Teoretycznie sprawa prosta w działaniu oraz w implementacji, ale czy przy większej ilości tras pasujących do danej ścieżki nie odbiłoby się to na wydajności? Czy ktoś spotkał się z takim routingiem lub może robił coś podobnego...?

Piszcie, co o tym myślicie.

Pozdrawiam
szaleq
irmidjusz
Robisz od nowa to, co już zrobiono z powodzeniem w istniejących frameworkach. Skoro tak bardzo chcesz wynajdywać ponownie koło, to może przeanalizuj istniejące rozwiązania i w ten sposób uzyskasz odpowiedzi na swoje pytania a przy okazji wiele się nauczysz. Żeby daleko nie szukać: Twój routing na razie wygląda identycznie jak zastosowany w Zend Framework.
szaleq
Przeglądałem wiele istniejących rozwiązań. Mimo wszystko tak już mam, że najwięcej uczę się sam "wynajdując koło od nowa" smile.gif
irmidjusz
Jesteś pewien, że się uczysz? To dość delikatna kwestia zahaczająca o kwestie natury psychologicznej.
Napisanie kodu samemu a zrozumienie jak działa kod napisany przez innych (i dlaczego tak został napisany) to różne sprawy. To drugie również jest bardzo wartościowe jeśli zmusza Cię do umysłowego wysiłku, aby zrozumieć dane rozwiązanie.
Rozpatrzmy taką sytuację: nie lubisz uczyć się z gotowych rozwiązań, bo Ci "nie wchodzą" do głowy, więc nie starasz się studiować już istniejącego kodu, tylko wolisz wymyślać własny. Ok, nawet jeśli stworzysz kod o analogicznym działaniu (zastosowaniu) to nadal możesz nie być w stanie zrozumieć kodu napisanego przez kogoś innego. A to jest ograniczeniem, z którego możesz nawet nie zdawać sobie sprawy. W Twoim umyśle (mózgu) istnieje pewna konceptualna reprezentacja tylko Twojego rozwiązania, a tymczasem inne rozwiązania mogą być o wiele lepsze, zawierać elementy, które w Twoim mózgu nie powstały i przez to te obszary koncepcji (abstrakcji) problemu są dla Ciebie zasadniczo niedostępne. Innymi słowy, można to w pewnym uproszczeniu ująć w ten sposób, że istniejące połączenia neuronalne w Twoim mózgu umożliwiają posługiwanie się pewnymi rozwiązaniami, ale siłą rzeczy nie masz dostępu do innych możliwych rozwiązań, bo odpowiednie sieci neuronowe w Twoim mózgu nie istnieją smile.gif I właśnie dlatego studiowanie gotowych rozwiązań jest bardzo pożyteczne (ale takie studiowanie do pełnego zrozumienia co, jak i dlaczego), bo to rozwija umysł - a dokładniej mózg smile.gif Zresztą, ten wysiłek, który się odczuwa przy próbie zrozumienia cudzego kodu pochodzi m.in. właśnie z faktu, że mózg nie umie tego ogarnąć, ale właśnie robienie tego bardzo go stymuluje. Podążanie łatwą, znaną ścieżką, która nie stanowi dla mózgu wyzwania (co oznacza brak stymulacji do tworzenia nowych połączeń między neuronami) jest może przyjemne i komfortowe, ale tak naprawdę nie wiele rozwija.
szaleq
@irmidjusz
Oczywiście, nie sposób nie przyznać Ci racji. Napisałem jednak, że "Przeglądałem wiele istniejących rozwiązań". Często zagłębiam się w kod licznych frameworków, przeglądam również np skrypty na phpclasses.org i wiele się w ten sposób uczę. Nie miewam problemów ze zrozumieniem czyjegoś kodu. Jednak po przestudiowaniu stu przykładów zawsze robię sto pierwszy po swojemu. I uważam, że słusznie.

Wracając do sedna tematu, akurat router Zenda przejżałem dość powierzchownie. Analizowałem jednak setki przykładów opisywanych na blogach, czy forach, przejżałem Symfony i Kohanę. No i np w kohanie wydaje mi się (może coś przeoczyłem?), że routing kończy się w momencie znalezienia pierwszej pasującej trasy. Moje pytanie dotyczy tylko i wyłącznie faktu, że aby szukać kolejnego dopasowania należy sprawdzić, czy pierwsze z brzegu dopasowanie jest prawdziwe co wiąże się z ładowaniem pliku klasu kontrolera. Sprawdzanie, czy plik istnieje, to dodatkowy czas i obciążenie dla serwera. Przy założeniu że mam kilka tras pasujących do danej ścieżki a w danym zapytaniu pasuje ostatnia trasa, muszę najpierw próbować załadować kilka plików nim trafię na ten właściwi. Czy to opłacalne? czy tak się robi? tylko o to pytam.
Jeśli sugerujesz, że tak właśnie działa routing w Zend Framework, dzięki za wskazówkę. Zagłębię się bardziej w jego kod.

Pozdrawiam
szaleq
irmidjusz
Cytat(szaleq @ 1.09.2012, 23:14:08 ) *
Jednak po przestudiowaniu stu przykładów zawsze robię sto pierwszy po swojemu. I uważam, że słusznie.

Też tak uważam.

A wracając do routingu, zasadniczo masz dwie podstawowe możliwości:

1) następuje tylko i wyłącznie dopasowywanie do istniejącego wzorca i pierwszy znaleziony jest uznawany za obowiązujący, więc jeśli nie istnieje spodziewany moduł/kontroler/akcja wynikający ze znalezionego wzorca, to jest błąd i koniec

W tym przypadku wszystko działa ok o ile wzorce dopasowań routingu są poprawnie określone - czyli m.in. nie może być niejednoznaczności w określaniu, jaką akcję wywołać, bo wykona się zawsze tylko pierwszy znaleziony. To rozwiązanie działa generalnie najlepiej, najprościej i najszybciej. W przedstawionym przez Ciebie zagadnieniu, jak sam zauważyłeś, ten sam wzorzec (<word1>/<word2>) chciałbyś móc rozwiązać na dwa wykluczające się sposoby (moduł/kontroler i kontroler/akcja). Z tego punktu widzenia, jest to po prostu błąd określania wzorców.

Możesz użyć też innego podejścia:

2) po znalezieniu wzorca, sprawdzane jest, czy aby odpowiedni moduł/kontroler/akcja istnieje, jak tak, jest wykonywana, jak nie, szukamy dalej...

I tak też można i będzie ok. Koszt sprawdzania jest różny - pytanie, czy w ogóle istotny. Generalnie można powiedzieć, że jeśli akcje są zaimplementowane jako metody kontrolerów, to sprawdzenie czy istnieje akcja w klasie kontrolera, który jest plikiem w folderze modułu, jest najbardziej kosztowne, więc lepiej sprawdzić jedynie, czy istnieje moduł <word1> a w nim kontroler <word2> (i wywołać akcję domyślną), a jak nie, to czy istnieje kontroler <word1> i wywołać w nim akcję <word2> (może być w odwrotnej kolejności). I są frameworki, które tak robią i żyją smile.gif Więc nie jest to problem.
Z głowy spraw wydajności nie określisz. To tylko testy realnie działającego kodu są w stanie poprawnie pokazać. A akurat sprawdzenie istnienia jednego czy dwóch plików więcej jednorazowo w czasie obsługi requesta na pewno nie będzie głównym problemem wydajności tongue.gif Nie mówiąc o tym, że możesz sobie np. napisać mechanizm, który na serwerze produkcyjnym skanuje wszystkie moduły, kontrolery i akcje i keszuje je do tablicy używanej przez routing. W tym podejściu, niejednoznaczne wzorce dopasowań routingu są akceptowalne a problemu z wydajnością może w ogóle nie być. Wszystko wedle życzenia, Twój projekt i jak zrobisz, tak będzie smile.gif A czy dobrze, czy źle, to pojęcie względne i zależy, wg. jakich założeń i miar oceniasz.


Z tym Zendem chodziło mi o to, że tam też jest <moduł/kontroler> i <kontroler/akcja>. Jest to rozwiązane tak (standardowo):
- jak podajesz tylko /<word1> to jest traktowane jako akcja w domyślnym kontrolerze w domyślnym module,
- <word1>/<word2> to jest uznawane za kontroler/akcja w domyślnym module,
- jak podasz <word1>/<word2>/<word3> to jest mapowane na moduł/kontroler/akcja (gdy masz moduły)

W ten sposób wszystkie trzy się łatwo od siebie odróżnia. Ładne w teorii, gdy nie ma parametrów. Zabawa się zaczyna, gdy podajesz parametry, hihi. No i tu będziesz miał zabawę z prześledzeniem rozwiązania ZF wink.gif
I zobacz jak jest w Yii, jak tam jest to dziwnie rozwiązane, i też działa i tyle ludzi go używa i jest ok.

To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.