Дозвольте мені пояснити обробку запиту WordPress та спосіб змінити поведінку WordPress для відповідного досягнення ваших цілей.
Розбір запиту
Коли WordPress отримує запит, він запускає процес розчленування запиту та перетворення його на сторінку. Ядро цього процесу починається, коли WP::main()
викликається основний метод запиту WordPress . Ця функція аналізує запит, як ви правильно визначили, в parse_request()
(в includes/class-wp.php
). Там WordPress намагається співставити URL-адресу з одним із правил перезапису . Коли збігається URL-адреса, він створює рядок запитів із частин URL-адреси та кодує ці частини (все між двома косою urlencode()
рисою ), використовуючи , щоб запобігти спеціальним символам, таким як &
не переплутати рядок запиту. Ці кодовані символи, можливо, змусили вас думати, що проблема там перебуває, але насправді вони перетворюються на їх відповідні "справжні" символи при розборі рядка запиту.
Запуск запиту, пов’язаного із запитом
Після того, як WordPress розібрав URL-адресу, він встановлює основний клас запитів WP_Query
, який робиться в тому ж main()
методі WP
класу. Яловичина файлу WP_Query
можна знайти в його get_posts()
методі, де всі аргументи запиту аналізуються та дезінфікуються та будується власне SQL-запит (і, зрештою, виконується).
У цьому способі в рядку 2730 виконується такий код:
$q['name'] = sanitize_title_for_query( $q['name'] );
Це дезінфікує публікацію для отримання її з таблиці повідомлень. Виведення інформації про налагодження всередині циклу показує, що саме тут і полягає проблема: ім'я вашої пошти my-permalink~
, перетворюється на my-permalink
, яке потім використовується для отримання публікації з бази даних.
Функція санітарії посади
Функція sanitize_title_for_query
викликає sanitize_title
відповідні параметри, яка переходить до очищення заголовка. Тепер основою цієї функції є застосування sanitize_title
фільтра:
$title = apply_filters( 'sanitize_title', $title, $raw_title, $context );
Цей фільтр, в рідному WordPress, одна функція додається до нього: sanitize_title_with_dashes
. Я написав обширний огляд того, що робить ця функція, яку можна знайти тут . У цій функції є рядок, який викликає вашу проблему
$title = preg_replace('/[^%a-z0-9 _-]/', '', $title);
Цей рядок позбавляє всіх символів, крім буквено-цифрових символів, пробілів, дефісів та підкреслень.
Вирішення вашої проблеми
Отже, існує в основному єдиний спосіб вирішити вашу проблему: вилучити sanitize_title_with_dashes
функцію з фільтра і замінити її на власну функцію. Це насправді зробити не так складно, але :
- Коли WordPress змінить внутрішній процес очищення заголовків, це матиме серйозні наслідки для вашого веб-сайту.
- Інші плагіни, що підключаються до цього фільтра, можуть неправильно працювати з новою функціональністю.
Найголовніше : WordPress використовує результат sanitize_title
функції безпосередньо в SQL запиті за цим рядком:
$where .= " AND $wpdb->posts.post_name = '" . $q['name'] . "'";
Якщо ви коли-небудь плануєте змінити фільтр, переконайтесь, що ви належним чином уникнути заголовка, перш ніж він буде використаний у запиті!
Висновок: вирішення проблеми не потрібно, що стосується безпеки, але якщо ви хочете це зробити, замініть sanitize_title_with_dashes
функціонал на власний та зверніть увагу на вихід SQL.
Зверніть увагу, що всі назви файлів та номери рядків відповідають файлам WordPress 4.4.2.