This post comes from the first version of this blog.
Please send me an email if anything needs an update. Thanks!

Routing w symfony 1.x jest rozwiązany w całkiem przyjemny sposób, jednak jak to zwykle bywa, kiedy próbujemy zrobić coś wbrew ustalonej konwencji, framework szybko sprowadza nas na “jedyną prawdziwą ścieżkę zen tworzenia aplikacji”. W dzisiejszym wpisie chciałbym przedstawić jeden z problemów, na jakie m0żemy trafić podczas zabawy z wspomnianym mechanizmem tytułowego frameworka.

Fotografia: filipw @ Fotolia.

symfony: Kropka w routingu aplikacji.

O co chodzi? Otóż, routing w symfony 1.x opiera się o tzw. "separatory segmentów" (segment separators), czyli znaki / stringi, które dzielą podany adres URL na fragmenty do dalszej analizy. Jeśli wykorzystujemy domyślne wartości ścieżek, to wartościami będą slash (/) i kropka (.).

Problem powstaje w miejscu, w którym chcielibyśmy, żeby jeden z separatorów stanowił wartość lub fragment wartości parametru. Rozważmy następującą ścieżkę:

userActivate:
  url: /user/:email/activate
  param:
    module: user
    action: activate

W tym momencie, jeśli do naszej aplikacji zostanie wystosowane żądanie:

/user/jan@kowalski.pl/activate
to wszystko będzie ok, symfony poprawnie odczyta wartość argumentu email i przekaże ją do kontenera. Jeśli jednak Pan Kowalski zechce być awangardowy i zamiast kupić sobie domenę założy sobie konto mailowe na GMailu, to wystosowane żądanie:
/user/jan.kowalski@gmail.com/activate
spowoduje, że symfony rzuci nam mało przyjazny błąd "empty module or action", co po polsku znaczy dokładnie tyle, że nie znaleziono żadnego (oczywiście poza modułem 404 :)) zasobu zdolnego obsłużyć podany adres URL.

Rozwiązanie.

Rozwiązanie tradycyjnie jest proste, problem należy do kategorii "wiedzy". Podczas deklarowania ścieżek w pliku routing.yml należy wykorzystać modyfikator "segment_separators", który określi, jakie znaki będą dzielić adres URL na fragmenty.

Przykładowe ustawienie:

userActivate:
  url: /user/:email/activate
  param:
    module: user
    action: activate
  options:
    segment_separators: [/]

spowoduje, że jedynym separatorem będzie znak ukośnika (/), a kropka w adresie email w niczym nie przeszkodzi przekazaniu danych do kontrolera “user” oraz akcji “activate”.

Oczywiście listą wartości w tym parametrze możemy się bawić do woli, ważne, żeby jednak pozostawić ten kluczowy slash, bo inaczej nic z tego nie będzie. :)

Mam nadzieję, że w erze Symfony2 tego typu wpis przyda się jeszcze osobom, które muszą utrzymywać aplikacje internetowe w wersji 1.x tego frameworka. Spokojnie, ja też muszę się jeszcze trochę z nim męczyć, więc nie jesteście sami. :)