Чому не слід використовувати query_posts() у WordPress
Якщо ви розробляєте теми та плагіни для WordPress, то ви, напевно, зустрічалися з функцієюquery_posts()у численних прикладах та уроках у мережі. У цій статті ми розповімо, чому вам не слід ніколи використовувати цю функцію.
Основні та вторинні запити
Основний запит (або основний цикл) WordPress це той, який виконується на ранньому етапі завантаження ядра, він будується з запитаного URL, налаштувань постійних посилань і т.д. Під час основного запиту WordPress визначає такі параметри як кількість записів на сторінку, шаблон, що використовується в темі та інші. Основний запит робить сам WordPress.
Вторинний запит це той, що виконується додатково до основного. Наприклад:
Основною відмінністюquery_posts()від інших допоміжних функцій є те, щоquery_posts()замінює основний цикл на новий, вторинний цикл WordPress. Це означає, що у циклі зquery_posts()ми можемо працювати так само, як і в звичайному основному циклі.
Для порівняння розглянемо цикл для виведення популярних записів за допомогоюWP_Query:
Цей же цикл за допомогоюquery_posts():
Безумовно другий варіант виглядає трохи чистішим і звичнішим, оскільки така конструкція найчастіше зустрічається при роботі з основним циклом WordPress.
Саме тому розробники часто думають, що query_posts() змінює основний запит WordPress, але це не так. Функціяquery_posts()замінює основний цикл на новий вторинний цикл, і відбувається цепіслявиконання основного запиту.
$wp_query та $wp_the_query
Щоб у цьому переконатися, достатньо поглянути на реалізацію подібних функцій:
Функціяquery_posts()створює новий вторинний запит за допомогоюWP_Queryі поміщаєрезультат у цю ж глобальну змінну$wp_query:
Таким чином, функції, які призначені для роботи з основним циклом WordPress починають працювати з нашим вторинним запитом, а основний запит залишився в глобальній змінній$wp_the_query, посилання на яку можна відновити за допомогою функціїwp_reset_query().
Після цього функціїhave_posts()та інші знову працюють з основним циклом WordPress, але розробники часто про це забувають, внаслідок чого перестає працювати пагінація, деякі віджети та інше.
Найчастішим результатом використанняquery_posts()є зламана пагінація, коли наприклад перші дві сторінки працюють, а третя та четверта повертають помилку 404. Давайте розглянемо як і чому це відбувається.
За промовчанням WordPress відображає десять записів на одній сторінці. Допустимо у нас лише двадцять записів, це лише дві сторінки. Змінити кількість записів на сторінку можна легко за допомогоюquery_posts()на початку нашого шаблону index.php або archive.php:
Таким чином, на кожній сторінці у нас буде п'ять записів, а не десять, а наш плагін для пагінації буде відображати чотири сторінки замість двох. Все сходиться, але при переході на третю сторінку ми отримуємо помилку 404. Чому це відбувається?
Нагадуємо, що основний запит WordPress відбувається ще до того, як обробляються шаблониindex.phpабоarchive.php, де відбувається наша «підміна». В основному запиті кількість записів на сторінку - десять, і лише дві сторінки. Третої та четвертої сторінок в основному запиті немає.
Саме основний запит визначає, який шаблон теми буде використовуватися, і при запиті третьої або четвертої сторінки WordPress використовуватиме шаблон404.php.
Подія pre_get_posts
Найбільш правильним способом змінити основний цикл WordPress є подіяpre_get_posts, яка відбувається перед кожним запитомWP_Query. Працювати з цією подією можна у плагіні або у файліfunctions.phpвашої теми:
Важливо, щоpre_get_postsвикликаєтьсядля кожногозапитуWP_Query>, включаючи основний запит, навігаційне меню, вторинні запити у віджетах та інше. За допомогою методуis_main_query()ми змінюємо параметри лише основного запиту, а за допомогою перевіркиis_admin()ми змінюємо запит лише на лицьовій частині сайту та не в адміністративній панелі.
Результат такого підходу той самий, що і зquery_posts(), але цього разу працюватиме пагінація, а завантаження сторінки відбуватиметься швидше, оскільки зpre_get_postsми дійсно змінили основний запит перед його виконанням та не виконували вторинних запитів.
Альтернативи query_posts()
Якщо вам потрібно виконати вторинний запит у WordPress, скористайтесь функцієюget_posts()або конструкцією newWP_Query(). При роботі з ними ваш код буде явнішим і зрозумілішим для читачів.
Коли потрібно змінити основний запит WordPress перед його виконанням, найпростішим способом є подіяpre_get_posts, або фільтр request, який виконується ще раніше, ніжpre_get_postsі тільки для основного запиту.
Додаткова інформація:Джерело: WP Magazine Функціяquery_posts()у кодексі (WP-Kama) Питання на форумі, пов'язане з виведенням схожих записів та функцією query_posts()