WordPress функция query_posts()

Тема для данной заметки навеяна проблемой, возникшей при переносе одного из блогов на VPS сервер. После переноса отказался работать плагин Advanced Category Excluder, который позволял отключить вывод постов из отдельной категории (или группы категория) в требуемых разделах блога, например, на главной странице или в архивах. В итоге, на главной оказались те публикации, которых там быть не должно. Более того, в общую ленту вылезли ревизии, картинки и файлы. В общем, все, что пишется в таблицу wp_posts, повалило в продакшен. Судя по всему, плагин отказывался работать на более новой версии PHP, хотя это более, чем странно. Выяснять истинные причины я выяснять не стал, так как разбираться в чужом коде не было желания, а просто поискал замену. Альтернатив оказалось не так много и все они показались мне совершенно неудобными в использовании. Было решено обойтись без плагина в принципе.

Я думаю, что решение достаточно верное, так как плагин Advanced Category Excluder не добавляет к движку ничего нового, а служит лишь оберткой для базовых функций WordPress, делающей работу с ними более комфортной.

У WordPress есть функция query_posts(), позволяющая переопределять стандартные запросы к базе данных, а следовательно, влиять на результаты выборки публикаций и страниц. Возможности ее очень богаты и можно без труда добиться практически любого результата.




Так, например, в предыдущей заметке я описывал процесс создания формы поиска и сортировок для каталога на WordPress, реализованного с помощью плагина Magic Fields. Желаемый эффект как раз достигался за счет использования query_posts(). Сегодня постараюсь развить тему.

Вызывать функцию query_posts() следует перед вызовом while (have_posts()). В качестве аргумента передается набор параметров, полным список которых, конечно же, можно найти в документации WordPress.

Так, например, чтобы добиться эффекта, который раньше создавался плагином Advanced Category Excluder, достаточно в индексном файле шаблона привести цикл вывода постов к следующему виду:

<?php query_posts('cat=-3'); ?>

<?php if (have_posts()) { ?>
	<?php while (have_posts()) { the_post() ?>
		...
	<?php } ?>
<?php } ?>

Такой вызов query_posts() исключает из выборки посты, принадлежашие к категории с ID равным 3.

Но есть один важный нюанс. Вызывая функцию query_posts() мы полностью переопределяем способ формирования SQL запроса к базе данных. Зачастую это лишнее и требуется только добавить новые условия к уже существующим, сгенерированным движком без нашего участия.

Для этого достаточно ввести переменную $query_string в текущую область видимости и конкатенировать ее с нашими дополнительными условиями выборки:

<?php global $query_string; query_posts($query_string . '&cat=-3'); ?>

<?php if (have_posts()) { ?>
	<?php while (have_posts()) { the_post() ?>
		...
	<?php } ?>
<?php } ?>

Собственно, то, что делал плагин Advanced Category Excluder, я реализовал путем добавления одной единственной строчки кода.

У меня нет большого желания перепечатывать родную документацию WordPress, которая, несомненно, значительно лучше меня расскажет обо всех возможностях функции query_posts(), но для полноты картины приведу несколько примеров из нее, снабдив их комментариями на русском языке.

Можно исключить из вывода публикации сразу из нескольких категорий, для этого достаточно перечислить их через запятую:

<?php
	query_posts('cat=-1,-2,-3');
?>

Также есть возможность вывести посты по имени категории:

<?php
	query_posts('category_name=software_news');
?>

Выведет пост из блога, ID которого равен 5

<?php
	query_posts('p=13');
?>

Следующий запрос комбинирует сразу несколько условий. Он выведет 5 постов из категории с ID 7, сортированных по дате (в обратном порядке), опубликованных в 2011 году:

<?php
	query_posts('cat=7&year=2011&orderby=date&order=DESC&posts_per_page=5');
?>

Данный способ определения запроса хорошо подходит в том случае, если вы не планируете полностью переопределить запрос, то есть вы будете использовать текущее значение $query_string. Если же текущее значение данной переменной вас не интересует, удобнее использовать ассоциативный массив в качестве аргумента query_posts():

<?php
$args = array(
	'post_type'=> 'movie',
	'actor'    => 'Bruce Campbell, Chuck Norris',
	'order'    => 'ASC'
);

query_posts($args);
?>

Официальная документация функции query_posts() находится в кодексе WordPress

Комментарии (4)

  1. Кирилл

    Полдня искал это)) query_posts(‘cat=7&posts_per_page=5’);
    Спасибо!)

    • На здоровье, только благодарить меня не за что :) Все это есть в официальной документации. Странно, что вы так долго искали нужную информацию, ведь она на поверхности.

  2. евгений

    Спасибо за крутую статью! Только я не смог разобраться как реализовать свою затею…
    Я хочу чередовать оформление постов на главной (и в категориях) таким образом:
    1 статья шириной во всю ширину, потом 3 статьи маленькие, все в ряд, потом опять широкая, потом 3 маленьких… То есть каждый n-й пост оформлять подругому… Такое можно сделать?
    Заранее спасибо!)

    • Ну во-первых, это можно сделать через CSS, используя псевдокласс :nth-child.

      Или в шаблоне добавить счетчик в цикл вывода постов и через условие if ($i == n) подгружать/формировать нужный шаблон.

      Что именно не получается? Задача простая же, кажется.

Добавить комментарий для Мурашов Олег Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *