parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

PF: Маршрутизация URLов и обработка параметров запросов

Sumo 25.08.2007 08:02 / 18.03.2011 07:15

Наше простейшее приложение сейчас не умеет ничего, кроме того, чтобы выводить одно и тоже сообщение на любой запрос. Ясно, что такое поведение нам не сильно интересно. Если мы хотим обработать URL вида /about/, то нам достаточно добавить в наш менеджер (/controllers/appManager.p) следующий метод:
@onAbout[aActionArgs]
  Информация об авторе!
Все! Теперь мы можем ввести в браузере http://localhost/about и получим "Информацию об авторе!". Не сложнее написать обработчики и для более сложных, вложенных URL'ов.
@onAboutContacts[aActionArgs]
# Обработчик для /about/contacts/
  ...

@onFirstSecondThird[aActionArgs]
# Обработчик для /first/second/third
  ...
В терминах PF URL с путем называется "экшн", а методы onXyz - обработчиками. PF не чувствителен к регистру символов в экшне (URL'е), а также игнорирует ведущие и конечные слеши.

Вы наверное уже заметили, что у обработчика есть единственный параметр - aActionArgs (вы можете назвать его как угодно!). В случае с pfSiteModule/pfSiteManager в эту переменную попадает хеш с полями http-запроса ($form:fields и $form:tables). Фактически внутри PF'а не возникает необходимости прямого обращения к классу form, что позволяет писать для модулей консольные unit-тесты, да и просто уменьшает связанность модуля с системой.

С простыми случаями понятно - написали обработчик и все. Предположим, что в нашем веб приложении должны присутствовать форум, блог, магазин и т.п. Понятно, что делать один большой модуль с кучей функций не эффективно. В этом случае PF приходит к нам на помощь.

Создадим модуль для блога (controllers/blogModule.p):
@CLASS
blogModule

@USE
pf/web/pfSiteModule.p

@BASE
pfSiteModule

@create[aOptions]
  ^BASE:create[$aOptions]

@onINDEX[aActionArgs]
  Это мой блог!
А в конструктор appManager'а добавим строки для регистрациии нашего нового модуля:
@create[$aOptions]
  ^BASE:create[$aOptions]
  ^addModule[blog;
      $.class[blogModule]
      $.file[blogModule.p]
  ]
Теперь по введя в браузер http://localhost/blog/ получим "Это мой блог!". При этом PF сам подключил и инициализировал необходимый класс. Вложенность модулей не ограничена, что позволяет строить из них достаточно сложные иерархии. Фактически это достаточно удобный способ для создания систем с плагинами.

Теперь немного подробнее об алгоритме поиска обработчиков для "экшнов" в pfSiteModule/pfSiteManager. Во всех модулях есть метод @dispatch[aAction;aActionArgs], который обеспечивает базоввую маршрутизацию. Получив экшн "about/contacts" метод разбирает его на части (по слешам), если удается найти модуль с названием "about" и передать управление ему, а если модуля нет, то ищем в модуле метод с именем onAboutContacts. Если метод найден, то передаем управление ему, а если и это не удалось, то вызывается метод onINDEX. Если определен метод onNOTFOUND, то в случае неправильного адреса экшна (для которого не нашли обработчик) вызывается именно он. В этом случае метод onINDEX будет вызываться только для "корневого" экшна ("/").

Но это еще не все. Нам необходимо не только уметь обработать экшн, но ставить на него ссылки нв страницах. Для этого в модулях имеется метод @linkTo[aAction;aOptions;aAnchor], который умеет формировать корректный URL для экшна. Самое интересное, что этот метод умеет формировать корректные ссылки даже, если модуль вложен в другой. Т.е. в нашем случае мы можем написать в классе blogModule следующий вызов ^linkTo[show/2007/08;$.sort_by[name];top] и получим в результате "/blog/show/2007/08?sort_by=name#top". Кроме того можно использовать метод @redirectTo[aAction;aOptions;aAnchor], который вызовет редирект на необходимый экшн. Единственное ограничение: параметр aAction методов linkTo и redirectTo всегда считается относительно текущего модуля. Если вам понадобится ссылка на родительский или любой другой модуль не включенный в текущий, то это прийдется организовывать через дополнительные классы (например, с использованием "медиатора").

Библиотека PF