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

Сьогодні можна побачити багато реалізацій використання символів кирилиці в рядку URL, які можуть відрізнятися способом відображення. Наприклад, замість пробілу може відображатися символ "+" або "-", а також "_". Зі сторони SEO досі тривають дискусії, який знак краще використовувати і як правильно оформити ЧПУ, але точно можна сказати, що є набагато більш важливіші показники SEO оптимізації, на які потрібно звертати увагу, крім рядка URL. У деяких вебсайтах взагалі пробіл не обробляється, а відображається як є, що також має свої переваги.

Використання в адресі URL лише символів латиниці унеможливлює появу багатьох проблем, які виникають при використанні кирилиці, наприклад, труднощів з кодуванням, незвичність для іноземних користувачів тощо. В більшості систем управління вебсайтами URL створюється або в ручному режимі латинськими літерами, або автоматичним перетворенням кирилиці в латиницю, тому URL завжди відображається в одному форматі. Але, як неважко помітити, кирилиця в URL використовується доволі часто, для прикладу, хештеги в соціальній мережі Facebook:
https://www.facebook.com/hashtag/літо
Тому, використання кирилиці в URL цілком гарна практика. Давайте розберемося, як правильно кодувати та декодувати URL за допомогою мови програмування PHP.

Для цього існують 2 взаємопов’язані функції: Urldecode та Urlencode. Urlencode повертає рядок, в якому всі не алфавітно-цифрові і символи, крім -_. будуть замінені знаком відсотка (%), за яким слідує два шістнадцяткових числа, а пробіли закодовані як знак додавання (+). Наприклад:
echo urlencode('php для початківця');
// php+%D0%B4%D0%BB%D1%8F+%D0%BF%D0%BE%D1%87%D0%B0%D1%82%D0%BA%D1%96%D0%B2%D1%86%D1%8F
Але, такий набір послідовностей ви не побачите, оскільки вебпереглядачі автоматично конвертують його в кирилицю.

Функція Urldecode - декодує всі кодовані послідовності %## в рядку. Символ "+" декодується в символ пробіла.

Функції Urlencode та Urldecode автоматично виконуються при відправленні даних методом GET та їх отриманні. Наприклад, створимо HTML форму з можливістю відправлення даних та отримаємо їх за допомогою суперглобального масиву $_GET:
echo '
<form action="/test.php" method="GET">
<input type="text" name="url" value="" />
<input type="submit" />
</form>';
echo $_GET['url'];
Введемо запит «котик + собачка» і отримаємо URL рядок:
/test.php?url=%D0%BA%D0%BE%D1%82%D0%B8%D0%BA+%2B+%D1%81%D0%BE%D0%B1%D0%B0%D1%87%D0%BA%D0%B0
Якщо замість введеного тексту ви отримали "котик+%2B+собачка", це означає, що веббраузер автоматично здійснив конвертацію даних у кирилицю з вище описаного посилання. Щоб отримати закодоване значення, можна скористатися наступним рішенням:
print_r(parse_url($_SERVER['QUERY_STRING']));
У змінній $_GET['url'] буде міститися наш базовий текст: "котик + собачка".

Аналогічні перетворення відбуваються після виконання наступного коду:
echo urlencode('котик + собачка'); // %D0%BA%D0%BE%D1%82%D0%B8%D0%BA+%2B+%D1%81%D0%BE%D0%B1%D0%B0%D1%87%D0%BA%D0%B0 
echo urldecode(urlencode('котик + собачка')); // котик + собачка
У значній більшості систем управління вебсайтами стрічка URL має більш гарніший вигляд з використанням модуля Mod_rewrite, який дозвволяє в адресі URL передавати дані у тому вигляді, який бажає використовувати розробник, наприклад, замість адреси:
test.php?url=котик+%2B+собачка
можна записати так:
/search/котик+%2B+собачка
Для цього створюється правило в .htaccess:
RewriteRule ^search/([^/]*)/?$ index.php?search=$1 [B,L]
Тому, ввівши у веббраузер URL адресу "/search/котик+%2B+собачка", змінна Search отримає необхідне значення.
Потрібно обов’язково використовувати прапор "B", який вказує RewriteRule екранувати НЕ-алфавітно-цифрові символи перед застосуванням трансформації.

Створена сценарієм структура URL адреси, яка містить символи "/" (%2F) та "\" (%5C), що надходять із зовнішніх джерел, у вебсервері Apache може призвести до помилки "404 Not Found The requested URL was not found on this server.". Сервер просто відхиляє URL адресу, не викликаючи mod_rewrite. Це рішення було зроблене в планах безпеки. Щоб вирішити цю проблему, найпростішим варіантом буде виконати подвійне кодування спеціальних символів слешів, реалізувавши наступну заміну:
$url = str_replace(array('%2F','%5C'), array('%252F','%255C'), urlencode($url));
Кодований символ "/" стає "%2F", а з подвійним кодуванням - "%252F".

Однак, варто сказати про існування ще двох функцій для кодування URL: Rawurlencode та Rawurldecode. Функція Rawurlencode здійснює кодування згідно RFC 3986 і повертає рядок, в якому всі не алфавітно-цифрові символи, крім -_.~, будуть замінені знаком відсотка (%), за яким слідує два шістнадцяткових числа. Це кодування служить для захисту буквених символів від інтерпретації в якості спеціальних обмежувачів URL і захищає їх від спотворення при передачі символів з подальшою конвертацією. Пробіли кодуються в %20, а не в +, як у випадку з Urlencode.

Які функції використовувати — залежить від конкретної ситуації, адже кодування рядка може використовуватися у багатьох випадках. Аналізуючи декілька систем управління вебсайтами можна помітити, що немає єдиної системи кодування, а кожна система має свій підхід, який базується на використанні в певних ситуаціях.

Я рекомендую, кодувати рядок за допомогою функції Rawurlencode:
echo '<a href="/questions/search/'.rawurlencode('котик і собачка').'">котик і собачка</a>';
А декодувати наступним методом:
trim(strval(rawurldecode($_REQUEST['search'])))
Слід зауважити, що у кодуванні декодування існує і безліч проблем, і більшість програмістів з ними рано чи пізно стикнеться. Деякі системи в межах необхідності використовують подвійне кодування. Для функції Urldecode можуть виникнути проблеми з пробілами та знаком +, оскільки в їх однакове представлення. Однак, кодування даних є необхідною операцією, яка захищає цілісність даних, тому, без сумніву, необхідно при будь-яких ситуаціях його виконувати.