Управління URL

Управління URL-адресами у веб-додатках включає у себе два аспекти:

  1. Додатку необхідно розібрати запит користувача, що надходить у вигляді URL, на окремі параметри.
  2. Додаток повинен надавати спосіб формування адрес URL, з якими воно зможе коректно працювати.

У додатках на Yii ці завдання вирішуються з використанням класу CUrlManager.

Примітка: Ви можете не користуватися Yii для генерації URL, однак, так робити не рекомендується, тому що ви не зможете легко поміняти URL додатка через конфігурацію без зміни коду.

Створення адрес URL

В принципі, адреси URL можна задати прямо в коді представлень контролера, проте куди зручніше створювати їх динамічно:



де $this відноситься до екземпляра контролера; $route відповідає маршруту запиту, а $params є списком параметрів GET для додавання до URL.

За замовчуванням, адреси створюються за допомогою createUrl в get-форматі. Наприклад, при значеннях параметрів $route='post/read' і $params=array('id'=>100), отримаємо такий URL:



де параметри зазначені у вигляді набору пар імʼя=значення, зʼєднаних знаком &, а параметр r вказує на маршрут. Однак, цей формат не дуже дружелюбний по відношенню до користувача.

Підказка: Для того, щоб згенерувати URL з хештегом, наприклад, /index.php?r=post/read&id=100#title, необхідно передати параметр # наступним чином: $this->createUrl('post/read',array('id'=>100,'#'=>'title')).

Ми можемо зробити так, щоб адреса, наведена у якості приклада вище, виглядала більш акуратно і зрозуміло за рахунок використання формату path, який виключає використання рядка запиту і включає всі GET-параметри в інформаційну частину адреси URL:



Для зміни формату представлення адреси URL, потрібно налаштувати компонент додатка urlManager таким чином, щоб метод createUrl міг автоматично переключитися на використання нового формату, а додаток міг коректно сприймати новий формат адрес URL:



Зверніть увагу, що вказувати клас компонента urlManager не потрібно, тому що він вже оголошений як CUrlManager в CWebApplication.

Підказка: Адреса URL, генерована методом createUrl є відносним. Для того, щоб отримати абсолютну адресу, потрібно додати префікс, використовуючи Yii::app()->request->hostInfo, або викликати метод createAbsoluteUrl.

Людинозрозумілі URL

Якщо у якості формата адреси URL використовується path, то ми можемо визначити правила формування URL, щоб зробити адреси більш привабливими і зрозумілими з точки зору користувача. Наприклад, ми можемо використовувати коротку адресу /post/100 замість довгого варіанту /index.php/post/read/id/100. CUrlManager використовує правила формування URL як для створення, так і для обробки адрес.

Правила формування URL задаються шляхом конфігурації властивості rules компонента додатку urlManager:



Правила задаються у вигляді масиву пар шаблон-шлях, де кожна пара відповідає одному правилу. Шаблон правила - рядок, який повинен збігатися із шляхом в URL. Шлях правила повинен вказувати на існуючий шлях контролера.

Крім показаного вище способу завдання правил, можна описати правило із зазначенням додаткових параметрів:



Починаючи з версії 1.1.7, можна використовувати показаний нижче формат. Тобто патерн вказується як елемент масиву, що дозволяє вказати кілька правил одного патерну:



Тут масив містить список додаткових параметрів для правила. Можливо вказати наступні параметри:

Використання іменованих параметрів

Правило може бути асоційоване з кількома GET-параметрами. Ці параметри вказуються у шаблоні правила у вигляді маркерів наступним чином:



де ParamName відповідає імені GET-параметра, а необовʼязковий ParamPattern - регулярному виразу, який використовується для перевірки відповідності значенню GET-параметра. Якщо ParamPattern не зазначений, то параметр повинен відповідати будь-яким символам, крім слеша /. У момент створення URL маркери будуть замінені на відповідні значення параметрів, а в момент обробки URL, відповідним GET-параметрами будуть присвоєні результати обробки.

Для наочності наведемо кілька прикладів. Припустимо, що наш набір правил складається з трьох правил:



При використанні createUrl для генерації адреси URL, маршрут і GET-параметри, передані методу, використовуються для визначення правила, яке потрібно застосувати. Правило застосовується у тому випадку, коли всі параметри, асоційовані з правилом, присутні серед GET-параметрів, а маршрут відповідає параметру маршруту.

Якщо ж кількість GET-параметрів більше, ніж вимагає правило, то зайві параметри будуть включені до рядка запиту. Наприклад, якщо викликати $this->createUrl('post/read',array('id'=>100,'year'=>2008)), ми отримаємо /index.php/post/100?year=2008. Для того, щоб зайві параметри були відображені в інформаційній частині шляху, необхідно додати до правила /*. Таким чином, використовуючи правило post/<id:\d+>/* отримаємо URL вигляду /index.php/post/100/year/2008.

Як вже говорилося, друге завдання правил URL - розбирати URL-запити. Цей процес зворотний процесу створення URL. Наприклад, коли користувач запитує /index.php/post/100, застосовується друге правило з прикладу вище і запит перетворюється в маршрут post/read і GET-параметр array('id'=>100) (доступний через $_GET).

Примітка: Використання правил URL знижує продуктивність додатку. Це відбувається з тієї причини, що у процесі парсинга запитаного URL CUrlManager намагається знайти відповідність кожного правила до тих пір, поки яке-небудь з правил не буде застосовано. Чим більше правил, тим більше втрати продуктивності. Тому у разі високонавантажених додатків використання правил URL варто мінімізувати.

Параметризація маршрутів

Ми можемо використовувати іменовані параметри у маршруті правила. Таке правило може бути застосоване до декількох маршрутах, що збігаються з правилом. Це може допомогти зменшити число правил і, таким чином, підвищити продуктивність додатку.

Для того, щоб показати параметризацію маршрутів, використовуємо наступний набір правил:



Ми використовували два іменованих параметри в маршруті правил: _c і _a. Перший відповідає назві контролера і може дорівнювати post або comment, другий - назві action-а і може приймати значення create, update або delete. Ви можете називати параметри по-іншому, якщо їх імена не конфліктують з GET-параметрами, які можуть використовуватися в URL.

При використанні правил, наведених вище, URL /index.php/post/123/create буде оброблено як маршрут post/create з GET-параметром id=123. По маршруту comment/list з GET-параметром page=2, ми можемо створити URL /index.php/comments?page=2.

Параметризація імен хостів

Також можливо використовувати імена хостів в правилах для розбору і створення URL. Можна виділяти частину імені хоста в GET-параметр. Наприклад, URL http://admin.example.com/en/profile може бути розібраний в GET-параметри user=admin і lang=en. З іншого боку, правила з іменами хостів можуть також використовуватися для створення URL адрес.

Щоб використовувати параметризрвані імена хостів, увімкніть імʼя хоста у правила URL:



Приклад вище говорить, що перший сегмент імені хоста повинен стати параметром user, а перший сегмент шляху — параметром lang. Правило відповідає маршруту user/profile.

Памʼятайте, що CUrlManager::showScriptName не працює при створенні URL адреси з використанням правил з параметризованим імʼям хоста.

Варто відзначити, що правило з параметризованим імʼям хоста не повинно містити піддиректорій у тому випадку, якщо додаток знаходиться у піддиректорії кореня веб-сервера. Приміром, якщо додаток розташовується за адресою http://www.example.com/sandbox/blog, ми повинні використовувати точно таке ж правило URL, як описано вище. Без піддиректорії: sandbox/blog.

Приховуємо index.php

З метою зробити адресу URL ще більш привабливою можна сховати імʼя вхідного скрипта index.php. Для цього необхідно налаштувати веб-сервер і компонент додатку urlManager.

Спочатку зконфігуруємо веб-сервер таким чином, щоб адреса URL без вказівки імені вхідного скрипта як і раніше передавався на обробку вхідного скрипта. Для сервера Apache HTTP server це досягається шляхом включення механізму перетворення URL і завданням кількох правил. Для цього необхідно створити файл /wwwroot/blog/.htaccess, що містить правила, наведені нижче. Ті ж правила можуть бути розміщені у файлі конфігурації Apache в секції Directory для /wwwroot/blog.



Далі потрібно встановити властивість showScriptName компонента urlManager рівним false.

Тепер, викликавши $this->createUrl('post/read',array('id'=>100)), ми отримаємо URL /post/100. Що важливо, ця адреса URL буде коректно розпізнана нашим веб-додатком.

Підміна закінчення у адресі URL

На додаток до всього перерахованого вище, ми можемо додати до наших адрес URL закінчення. Наприклад, ми можемо отримати /post/100.html замість /post/100, представивши користувачеві начебто статичну сторінку. Для цього потрібно просто налаштувати компонент urlManager шляхом встановлення властивості urlSuffix будь-якого бажаного закінчення.

Використання свого класу правила URL

Примітка: дана можливість доступна з версії 1.1.8.

За замовчуванням кожне правило URL для CUrlManager представлено обʼєктом класу CUrlRule. Цей обʼєкт розбирає запити і створює URL по заданому правилу. Незважаючи на те, що CUrlRule досить гнучкий і підходить для роботи із більшістю форматів URL, іноді потрібні які-небудь особливі можливості.

Наприклад, для сайту з продажу автомобілів може знадобитися підтримувати URL виду /Виробник/Модель, де і Виробник і Модель повинні відповідати даним з певної таблиці бази даних. У цьому випадку клас CUrlRule не підійде так як він, в основному, працює із статично описаними регулярними виразами, а не з базою даних.

У даному випадку можна реалізувати новий клас правила URL, успадкувавши CBaseUrlRule, і використовувати його в одному або декількох правилах. Для наведеного вище прикладу з продажу автомобілів підійдуть такі правила URL:



Вище ми використали свій клас правила URL CarUrlRule для обробки URL вигляду /Виробник/Модель. Даний клас може бути реалізований наступним чином:



Свій клас правила URL повинен реалізувати два абстрактних методи, оголошених у CBaseUrlRule:

Крім показаного вище типового використання, свій клас URL може стати у нагоді і в інших ситуаціях. Наприклад, можна реалізувати клас правила, який буде записувати у журнал адреси URL, що розбираються і створюються. Це може стати у нагоді на етапі розробки. Також можна реалізувати клас, який показує особливу сторінку помилки 404 у тому випадку, коли всі інші правила не спрацювали для адреси URL, що розбирається. Варто зазначити, що в цьому випадку правило з цим спеціальним класом повинно вказуватися останнім у списку.