1

Topic: Как правильно делать SQL запросы к базе данных WordPress

Вывод случайных записей на сайте WordPress является очень полезным ходом, так как это позволяет не только создать внутреннюю перелиновку, что хорошо с точки зрения оптимизация для выдачи в поисковых системах, но и помогает показать пользователям записи, которые были опубликовано достаточно давно и возможно уже оказались незаслуженно забытыми. А именно как раз эти записи могут оказаться очень полезными для некоторых, поэтому периодически поднимать их из архива очень необходимо.

Поскольку нам нужно вывести именно случайные записи в нужном месте, то как никак лучше подойдет такая функция WordPress, как query_posts. Она позволяет выводить записи согласно заданным критериям, например только из определенной категории или вообще только определенные записи. Теперь расскажу немножко подробнее об этой функции и приведу несколько примеров, чтобы вы имели о ней представление. Для обычного вывода записей в WordPress используют цикл, так называемый “The Loop”. Обычно он выглядит вот так:

<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_posts(); ?>
//Ваш код
<?php endwile; ?>

Если перед этим циклом поставить функцию query_post с нужными нам параметрами, то можно добиться вывода записей в случайном порядке. Приведу первый пример:

<?php query_posts('cat=-1,-2,-3'); ?>
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_posts(); ?>
//Ваш код
<?php endwile; ?>

Такой код выведет записи из всех категорий, кроме категорий с ID 1, 2 и 3.

Теперь, когда вам понятно что делает эта функция и принцип задания параметров, приведу остальные виды параметров для query_posts:

query_posts(‘cat=-3′) – Не показывать категорию с id=3;
query_posts(‘cat=-1,-2,-3′) – Не показывать категории с id, равным 1, 2 и 3;
query_posts(‘cat=1,5,9′) – Вывести категории с id, равным 1, 5 и 9;
query_posts(‘category_name=Статьи’) – Вывести категорию с названием “Статьи”;
query_posts(‘name=Возможности WordPress’) – Вывести запись с названием “Возможности WordPress”;
query_posts(‘p=12′) – Вывести одну запись, id которой равно 12;
query_posts(‘pageid=8′) – Вывести одну страницу, id которой равно 8;
query_posts(‘pagename=Об авторе’) – Вывести страницу, название которой “Об авторе”;
query_posts(‘cat=3&showposts=5′) – Вывести 5 записей из категории, id которой равно 3;
query_posts(‘cat=3&orderby=date&order=ASC’) – Вывести записи из категории, id которой равен 3 по дате в хронологическом порядке, т.е выше будут распологаться записи, которые были созданы последними. Если вам надо вывести записи в обратном порядке, то нужно применить параметр DESC;
query_posts(‘posts_per_page=10′) – Вывести на страницу 10 записей. Если задать значение ‘-1′, то будут выводиться все записи;
query_posts(‘cat=3&year=2010′) – Вывести записи из категории, id которой равен 3, за 2010 год;
query_posts(‘orderby=rand&showposts=5&cat=3′) – Вывести случайно 5 записей из категории, id которой равен 3;
query_posts(‘orderby=rand&showposts=5′) - Вывести случайно 5 записей из всех категорий;
query_posts(‘meta_key=cars&meta_value=volvo’) – Вывести список записей с произвольным полем “cars” и значением этого поля “volvo”.

Лучше не забивать кодом основные файлы шаблона, а выносить его в виде функции в файл functions.php, присваиваю ей имя, а затем в нужном мне месте прописываю только имя этой функции всего лишь одной строчкой. Приведу пример в нашем случае:

<?php
function randomPosts() {
query_posts('orderby=rand&showposts=10');
if (have_posts()) : while (have_posts()) : the_post(); ?>
   <ul>
     <li><a title="<?php the_title(); ?>" href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
   </ul>
<?php endwhile; endif;
}
?>

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

<?php randomPosts(); ?>

Как видите, все получается чистенько и аккуратно, можете даже написать комментарий в этом месте, пояснив, вывод какой именно функции здесь осуществляется.

1

2

Re: Как правильно делать SQL запросы к базе данных WordPress

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

Для сравнения рассмотрим цикл для вывода популярных записей с помощью WP_Query:

// Вторичный цикл
$popular = new WP_Query( ... );
while ( $popular->have_posts() ) {
    $popular->the_post();

    the_title(); // вывести название
    the_content(); // вывести содержимое
}

Этот же цикл с помощью query_posts():

// Вторичный цикл
query_posts( ... );
while ( have_posts() ) {
    the_post();

    the_title(); // вывести название
    the_content(); // вывести содержимое
}

Безусловно второй вариант выглядит немного чище и привычнее, поскольку такая конструкция чаще всего встречается при работе с основным циклом WordPress.

Именно поэтому разработчики часто думают, что query_posts() изменяет основной запрос WordPress, но это не так. Функция query_posts() заменяет основной цикл новым вторичным циклом, и происходит это после выполнения основного запроса.

3

Re: Как правильно делать SQL запросы к базе данных WordPress

query_posts() предназначена для самого WordPress и должна использоваться для изменения основного Цикла WordPress, если нужно создать еще одни цикл, то используйте get_posts() или WP_Query. С версии 3.0 эти функции могут принимать все те же параметры что и query_posts().

Пример использования get_posts() вместо query_posts():

$args = array( 'posts_per_page' => 3 );
$lastposts = get_posts( $args );
foreach( $lastposts as $post ){ setup_postdata($post);
  ?>
  <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
  <?php 
  the_content(); 
}
wp_reset_postdata();

Пример использования WP_Query вместо query_posts():

$args = array( 'posts_per_page' => 3 );
$query = new WP_Query( $args );
while ( $query->have_posts() ) {
  $query->the_post();

  the_title(); // выведем заголовок поста
}
wp_reset_postdata();

Почему нельзя использовать query_posts()?

Основной запрос WordPress это запрос, который выполняется до вывода какого-либо текста на страницу (на раннем этапе). Параметры такого запроса собирает сам WP опираясь на: запрошенный URL; настройки ЧПУ (постоянных ссылок) и др. Так WordPress определяет сколько записей показать на странице, записи из какой рубрики показывать и т.д.

А вторичный запрос это тот, который создается пользователем (темой, плагином) и выполняется дополнительно к основному. Например: Вывод в сайдбаре списка популярных записей; Вывод комментируемых записей.

Так вот, если использовать query_posts() для создания вторичных запросов (циклов), то могут появится ошибки из-за которых будет рушится структура и тип страниц, так как повторный вызов query_posts() переписывает базовый запрос WP, на основе которого определяется тип текущей страницы (запись, рубрика), определяется сколько записей показывать на странице (пагинация) и многое другое.

Разница между query_posts() и WP_Query в том, что query_posts() создает новый WP_Query объект и связывает его с глобальной переменной $wp_query, тогда как get_posts() или WP_Query() создает новый WP_Query объект, без изменения каких-либо глобальных данных.

Давайте рассмотрим на примере:

// Пример 1: Дополнительный запрос с помощью query_posts

query_posts( $args );
while ( have_posts() ) {
  the_post();

  the_title(); // вывести название
}

// Пример 2: Дополнительный запрос с помощью WP_Query

$second_query = new WP_Query( $args );
while ( $second_query->have_posts() ) { $second_query->the_post();

  the_title();
}

Тут, первый пример переписывает глобальные переменные $wp_query, $post, $posts, а второй работает автономно и ничего не меняет.

Чтобы более детально понять разницу прочитайте статью о 3х способах построения циклов в WordPress.

Если вы по каким-то причинам вынуждены использовать query_posts(), то после цикла обязательно используйте wp_reset_query() - сбрасывает глобальные переменные запроса на начальные.

4

Re: Как правильно делать SQL запросы к базе данных WordPress

WP_Query - это PHP класс, который позволяет получать посты из базы данных по самым разным критериям. Например, мы можем получить посты:

за определенный промежуток времени;
из указанной категории, метки;
свежие посты, случайные посты, популярные посты;
и много других операций.

WP_Query используется в WordPress всегда. Например, во время генерации любой страницы WP_Query создает глобальную переменную $wp_query где хранится информация о текущем запросе. На основе этой информации WP определяет на какой странице мы сейчас находимся (пост, архив, метка и т.д.). Также при построении базового цикла WordPress, данные берутся из переменной $wp_query и выводятся на экран через вспомогательные функции: the_permalink(), the_content(). Также, $wp_query хранит и другие данные. На разных типах страниц данные разные. Посмотреть какие данные находятся в переменной $wp_query можно так:

global $wp_query;
print_r($wp_query);

Также код цикла может выглядеть так (тоже самое что get_post(), только без предустановленных параметров):

$my_posts = new WP_Query;
$myposts = $my_posts->query( array(
  'post_type' => 'page'
) );
foreach( $myposts as $pst ){
  echo $pst->post_title;
}

5

Re: Как правильно делать SQL запросы к базе данных WordPress

Стандартный цикл:

// задаем нужные нам критерии выборки данных из БД
$args = array(
  'posts_per_page' => 5,
  'orderby' => 'comment_count'
);

$query = new WP_Query( $args );
// Цикл
if ( $query->have_posts() ) {
  while ( $query->have_posts() ) {
    $query->the_post();
    echo '<li>' . get_the_title() . '</li>';
  }
} else {
  // Постов не найдено
}
/* Возвращаем оригинальные данные поста. Сбрасываем $post. */
wp_reset_postdata();

6

Re: Как правильно делать SQL запросы к базе данных WordPress

Множественный цикл:

// Запрос к БД

$the_query = new WP_Query( $args );

// Цикл

while ( $the_query->have_posts() ) {
  $the_query->the_post();
  echo '<li>' . get_the_title() . '</li>';
}
/* Восстанавливаем оригинальные данные 
 * Так как мы используем new WP_Query мы не влияем на
 * переменную $wp_query и нет необходимости сбрасывать запрос,
 * поэтому сбрасываем только данные поста.
*/
wp_reset_postdata();

/* Второй запрос (без глобальной переменной) */

$query2 = new WP_Query( $args2 );

// 2-й Цикл

while( $query2->have_posts() ) {
  $query2->next_post();
  echo '<li>' . get_the_title( $query2->post->ID ) . '</li>';
}

// Восстанавливаем оригинальные данные поста

wp_reset_postdata();

7

Re: Как правильно делать SQL запросы к базе данных WordPress

Аналог get_posts():

$args = array(
  'post_type' => 'page'
);
$query = new WP_Query;
$my_posts = $query->query($args);

foreach( $my_posts as $my_post ){
  echo '<p>'. $my_post->post_title .'</p>';
}

8

Re: Как правильно делать SQL запросы к базе данных WordPress

Сортирует и устанавливает направление сортировки.

order(строка)
Направление сортировки по параметру orderby, может быть:

ASC - по порядку, от меньшего к большему (1, 2, 3; a, b, c).
DESC - в обратном порядке, от большего к меньшему (3, 2, 1; c, b, a) .
orderby(строка)

Поля по которым можно сортировать посты. Может быть

none - не сортировать, выводить прям как находиться в БД. равносильно сортировке по ID. С версии 2.8.
ID - сортировка по ID.
author - сортировка по ID авторов.
title - сортировка по заголовку.
name - по названию поста (ярлык, слаг поста).
date - сортировка по дате публикации.
modified - сортировка по дате изменения.
type - по типу поста (post_type). С версии 4.0
parent - сортировка по значению поля parent.
rand - случайный порядок.
comment_count - сортировка по количеству комментариев. С версии 2.9.
menu_order - стандартно используется для страниц и вложений. Порядковый номер указывается на странице редактирования поста.
meta_value Важно: параметр meta_key так же должен быть определен. Заметка: сортировка будет алфавитной и будет не логична, если значения
произвольных полей числа (будет, например, так 1, 3, 34, 4, 56, 6 и т.д., а не 1, 3, 4, 6, 34, 56).
meta_value_num - сортировка по произвольным полям значения которых являются числами. С версии 2.8.
post__in - учитывает порядок указанных ID в параметре post__in.
'orderby' = array()
С версии WordPress 4.0 в orderby можно указывать массив сочетающий в себе оба параметра: orderby и order. Сделано это для сортировки по нескольким колонкам одновременною Синтаксис такой:

'orderby' => array( 'title' => 'DESC', 'menu_order' => 'ASC' )

Примеры

#1 Сортировка по заголовку

$query = new WP_Query( array ( 'orderby' => 'title', 'order' => 'DESC' ) );

Отсортируем по порядку в меню, а затем по заголовку

$query = new WP_Query( array ( 'orderby' => 'menu_order title', 'order' => 'DESC' ) );

#2 Выведем один случайный пост:

$query = new WP_Query( array ( 'orderby' => 'rand', 'posts_per_page' => '1' ) );

#3 Отсортируем посты по количеству комментариев:

$query = new WP_Query( array( 'orderby' => 'comment_count' ) );

#4 Отсортируем продукты по цене (произвольное поле price):

$query = new WP_Query( 
   array ( 'post_type' => 'product', 'orderby' => 'meta_value', 'meta_key' => 'price' ) 
);

#5 Множественная сортировка

Выведем посты отсортированные по двум полям: 'title' и 'menu_order' (title первостепенен):

$query = new WP_Query( 
  array( 'post_type' => 'page', 'orderby' => 'title menu_order', 'order' => 'ASC' ) 
);

#6 Множественная сортировка с использованием массива (с версии 4.0)

Получим страницы отсортированные по заголовку (title) и номеру меню (menu_order) в разном порядке (ASC/DESC):

$query = new WP_Query( array( 'orderby' => array( 'title' => 'DESC', 'menu_order' => 'ASC' ) ) );

#7 Сортировка по 'meta_value' для нового типа поста (post_type)

Выведем посты типа 'my_custom_post_type' отсортированные по ключу произвольного поля "age" и отфильтрованные, чтобы показывались только посты со значением поля 3 и 4:

$args = array(
   'post_type' => 'my_custom_post_type',
   'meta_key' => 'age',
   'orderby' => 'meta_value_num',
   'order' => 'ASC',
   'meta_query' => array(
     array(
       'key' => 'age',
       'value' => array(3, 4),
       'compare' => 'IN',
     )
   )
 );
 $query = new WP_Query($args);