3 способа построения циклов в wordpress

Содержание:

Произвольные поля (postmeta)

Удаляем ненужные произвольные поля

Стоял плагин и создавал себе произвольные поля, как вдруг — он стал не нужен и вы его удалили, а осиротелые, никому не нужные произвольные поля остались в Базе Данных. В такой или подобной ситуации, все произвольные поля с названием, например можно удалить таким простым SQL запросом:

DELETE pm FROM wp_postmeta pm WHERE pm.meta_key = 'meta_name'

Если название произвольного поля (meta_name) в кириллице, то убедитесь, чтобы кодировка файла из которого будет производиться SQL запрос соответствовала кодировке блога (обычно UTF-8 без BOM).

Получим все произвольные поля с пустым значением

Несмотря на то, что в админке создать произвольное поле не задав ему никакое значение не получится, по крайней мере стандартными средствами, такие «пустые» произвольные поля все же могут быть в вашей Базе Данных. Например, их могут оставить всякие там плагины или кривые руки. Чтобы посмотреть есть ли подобные поля и затем решить их судьбу, воспользуетесь таким SQL запросом:

SELECT *
FROM wp_postmeta pm
LEFT JOIN wp_posts wp ON wp.ID = pm.post_id
WHERE wp.ID IS NULL

Использование WP_Query в темах и плагинах

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

Рассмотрим простую ситуацию:

// Основной цикл
while ( have_posts() ) :
    the_post();
    the_title(); // вывести заголовок

    // Вторичный цикл, например схожие статьи
    $related = new WP_Query( ... );
    while ( $related->have_posts() ) :
        $related->the_post();
        the_title(); // заголовок схожей статьи
    endwhile;
endwhile;

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

Именно поэтому, если слегка изменить наш код:

// Основной цикл
while ( have_posts() ) :
    the_post();
    the_title(); // вывести заголовок

    // Вторичный цикл, например схожие статьи
    $related = new WP_Query( ... );
    while ( $related->have_posts() ) :
        $related->the_post();
        the_title(); // заголовок схожей статьи
    endwhile;

    // Снова заголовок. в чём ошибка?
    the_title();
endwhile;

Мы получаем, на первый взгляд, совершенно непредсказуемый результат. Третий вызов функции выведет заголовок последней записи из вторичного цикла, несмотря на то, что вызов функции находится за пределами этого цикла.

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

Функция wp_reset_postdata()

Функция устанавливает глобальную переменную в её исходное значение: текущая запись основного цикла. Использовать данную функцию следует сразу же после завершения нашего вторичного цикла:

// Основной цикл
while ( have_posts() ) :
    the_post();
    the_title(); // вывести заголовок

    // Вторичный цикл, например схожие статьи
    $related = new WP_Query( ... );
    while ( $related->have_posts() ) :
        $related->the_post();
        the_title(); // заголовок схожей статьи
    endwhile;

    // Вернуть $post в исходное значение
    wp_reset_postdata();

    // Всё ок!
    the_title();
endwhile;

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

Пример простого плагина

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

<?php
/**
 * Plugin Name: Append Latest Posts to Content
 */
function my_append_latest_posts( $content ) {
    $query = new WP_Query( array(
        'posts_per_page' => 5,
        'post__not_in' => array( get_the_ID() ),
    ) );

    if ( ! $query->have_posts() )
        return $content;

    $content .= '<h3>Свежие записи</h3>';
    $content .= '<ul>';

    while ( $query->have_posts() ) :
        $query->the_post();
        $content .= sprintf( '<li><a href="%s">%s</a></li>',
            esc_url( get_permalink() ),
            get_the_title()
        );
    endwhile;

    $content .= '</ul>';

    // Не забываем
    wp_reset_postdata();

    return $content;
}
add_action( 'the_content', 'my_append_latest_posts' );

При активации данного плагина пять последних статей будут выводиться списком со ссылками после содержимого каждой записи

Обратите внимание на параметр , с помощью которого мы исключаем текущую запись из нашего списка

Последние записи

Изменив параметры в обращении к , вы легко можете реализовать блок схожих записей, популярных записей, записей с наибольшим количеством комментариев и многое другое.

После того, как вы освоили основы работы с классом , мы советуем ознакомиться с его остальными методами и переменными, например , , , и другие. Если вам интересно узнать, как именно работает , загляните в файл wp-includes/query.php.

Если у вас возникли вопросы при работе с , оставьте комментарий и мы обязательно вам ответим.

Удаляем ревизии (редакции) записей

По умолчанию в WordPress включены ревизии записей. Они засоряют базу данных и редко по-настоящему нужны. Если ревизии у вас включены, то я рекомендую, очищать из хотя бы раз в год. Сделать это можно таким запросов в phpMyAdmin:

-- зависимость с таксономиями
DELETE FROM wp_term_relationships WHERE object_id IN (SELECT ID FROM wp_posts WHERE post_type = 'revision');

-- метаполя
DELETE FROM wp_postmeta WHERE post_id IN (SELECT ID FROM wp_posts WHERE post_type = 'revision');

-- сами ревизии
DELETE FROM wp_posts WHERE post_type = 'revision';

Данный запрос удалить редакции записей и автосохранения. Также удалит связанные метаполя (если они есть) и связь ревизии с таксономией (если она есть).

Вариант 2

В качестве альтернативного запроса, можете воспользоваться таким. Это пример удаления с JOIN:

DELETE a,b,c,d
	FROM wp_posts a
		LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id)
		LEFT JOIN wp_postmeta c ON (a.ID = c.post_id)
		LEFT JOIN wp_comments d ON (a.ID = d.comment_post_ID)
	WHERE a.post_type = 'revision'

2) Цикл на основе WP_Query()

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

Интересно, что WP_Query является ядром функций query_posts() и get_posts(), т.е. обе эти функции работают на основе этого класса.

Пример цикла: выведем все записи из категории 9:

<?php
// указываем категорию 9 и выключаем разбиение на страницы (пагинацию)
$query = new WP_Query( 'cat=9&nopaging=1' ); 
if( $query->have_posts() ){
	while( $query->have_posts() ){
		$query->the_post();
		?>
		<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
		<?php the_content(); ?>
		<?php
	}
	wp_reset_postdata(); // сбрасываем переменную $post
} 
else
	echo 'Записей нет.';
?>

Пример создания множественных циклов на основе WP_Query():

<?php
// Цикл 1
$query1 = new WP_Query('cat=-1&nopaging=1'); // все посты, кроме категории 1
while( $query1->have_posts() ){
	$query1->the_post();

	// вывод записей
}
wp_reset_postdata();

// Цикл 2
$query2 = new WP_Query('cat=-2&nopaging=1'); // все посты, кроме категории 2
while( $query2->have_posts() ){
	$query2->the_post();

	// вывод записей
}
wp_reset_postdata();

// Цикл 3
$query3 = new WP_Query('cat=-3&nopaging=1'); // все посты, кроме категории 3
while( $query3->have_posts() ){
	$query3->the_post();

	// вывод записей
}
wp_reset_postdata();
?>

Особенность циклов на WP_Query() в том, что мы создаем новый объект $query, который никак не связан с аналогичным глобальным объектом $wp_query и поэтому мы никак не нарушаем структуру текущей страницы.

Также, мы можем использовать новый объект в других целях, не только для вывода записей, но и для различного рода проверок: например, записи какого типа страницы  используются в этом новом объекте; можем узнать общее количество записей удовлетворяющих запросу ($query->found_posts) и т.д. Такие данные могут пригодится при создании дополнительных запросов с пагинацией или где-то еще ().

Зачем нужно использовать wp_reset_postdata()?

В глобальной переменной $post хранятся данные текущего поста (если показывается страница поста, то данные этого поста). Когда срабатывает часть кода , то в переменную записываются данные текущего поста в цикле и в конце цикла в этой переменной остаются данные последнего поста из этого цикла, а нужно чтобы $post всегда содержала данные текущего поста страницы. Т.е. получается до использования цикла (ID текущего поста) было равно, допустим, 10, а после срабатывания цикла, та же самая переменная уже равна, допустим, 56 (ID последнего поста из цикле), а нужно чтобы она по-прежнему равнялась 10.

wp_reset_postdata() используется как раз для того, чтобы вернуть правильные данные в переменную $post.

Когда использовать WP_Query()?

Если нужно вывести записи не затрагивая основной цикл (допустим записи в боковой панели), если нужно создать множественные запросы. Вообще, я не вижу никаких преимуществ циклов на WP_Query() над циклами с использованием get_posts() и поэтому рекомендую использовать get_posts() вместо WP_Query().

3) Цикл на основе get_posts()

Самый удобный вариант выводить нужные записи в нужном порядке — это выводить их с помощью get_posts() (см. описание). get_posts() в 99% случаев полностью заменяет WP_Query(): нужно вывести 10 последних постов в сайдбаре или 10 случайных записей в подвале — пожалуйста; нужно вывести все картинки прикрепленные к посту или вывести записи с определенным произвольным полем — get_posts() прекрасно справится с этой задачей.

get_posts() так же как и query_posts() работает на основе класса WP_Query() и поэтому передаваемые параметры одинаковые (см. их здесь).

#1. Пример цикла на основе get_posts(). Выведем 5 записей из рубрики 9:

<?php
global $post; // не обязательно

// 5 записей из рубрики 9
$myposts = get_posts( array(
	'category' => 9
) );

foreach( $myposts as $post ){
	setup_postdata( $post );

	// стандартный вывод записей
}

wp_reset_postdata(); // сбрасываем переменную $post
?>

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

Всегда, когда нужно просто вывести записи из БД в любом месте шаблона. Когда нужно создать несколько циклов. Так как get_posts() принимает те же параметры что и query_posts(), её очень удобно использовать для вывода записей по самым разным критериям.

Пагинация

Самым частым результатом использования является сломанная пагинация, когда например первые две страницы работают, а третья и четвертая возвращают ошибку 404. Давайте рассмотрим как, и почему это происходит.

По умолчанию WordPress показывает десять записей на одной странице. Допустим у нас всего двадцать записей, это всего две страницы. Изменить количество записей на страницу можно легко с помощью в начале нашего шаблона index.php или archive.php:

global $query_string;
query_posts( $query_string . '&posts_per_page=5' );

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

Напоминаем, что основной запрос WordPress происходит еще до того, как обрабатываются шаблоны index.php или archive.php, где происходит наша «подмена». В основном запросе количество записей на страницу — десять, и всего две страницы. Третей и четвертой страниц в основном запросе нет.

Именно основной запрос определяет какой шаблон темы будет использоваться, и при запросе третей или четвертой страницы WordPress будет использовать шаблон 404.php.

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

О записях в WordPress: где хранятся в базе данных, и как их получить

Абсолютно все записи в WordPress, про которые чуть ниже, хранятся в одной таблице: . Метаданные постов, например, данные из метабоксов Yoast SEO, хранятся в таблице .

Приведу пример, как получить 10 записей типа (стандартные Записи в панели администратора).
В общих чертах, данные особо запрашивать не надо. В шаблонах они уже предустановлены, например, в данные по записи уже доступны для обработки в цикле

if ( have_posts() ) {
   while ( have_posts() ) { the_post();
      // Тут используем данные из цикла, такие как the_title() и т.п.
   }
}

Если данные нужно получить где-то вне цикла или шаблона, используется запрос

$args = array(
	'post_type' => 'post', // Тип поста: page, attachment, ...
	'posts_per_page' => 10, // 10 записей за раз
);
$p = get_posts( $args );

// Данные можно раскрыть в цикле
if ( !empty( $p ) ) {
	foreach ( $p as $post ) {
		setup_postdata( $post );
		?>
		<a href="<?= the_permalink() ?>"><?= the_title() ?></a>
		<?php
	} wp_reset_postdata();
}

Данные можно получить посредством SQL запроса:

global $wpdb;
$query = "SELECT * FROM {$wpdb -> posts} WHERE post_type = 'post' LIMIT 10";
$p = $wpdb -> get_results( $query );
exit( print_r( $p ) ); // в $p теперь массив с данными о постах

Все три способа выше дадут одинаковый результат на выходе.

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

Проблема

Большинство современных тем, а особенно «журнальные» темы, выводят как минимум два главных цикла на главной странице. Данный метод очень полезен, например, для раздела «выделенные записи». Но, если использование двух главных циклов на странице реализуется легко, то предотвратить вывод дублирующихся записей не так просто. Пока вы не знаете о данном методе.

Решение

1. Начнем с первого главного цикла. Ничего сложного: в примере мы просто получаем 8 последних записей с помощью параметра . Открываем файл index.php и вставляем в него  следующий код:

<?php
query_posts('showposts=8');
$ids = array();
while (have_posts()) : the_post();
$ids[] = get_the_ID();
the_title();
the_content();
endwhile;
?>

2. Затем наступает время реализовать второй главный цикл. В нем мы получаем все записи, за исключением тех, которые уже выведены в первом цикле:

<?php
query_posts(array('post__not_in' => $ids));
while (have_posts()) : the_post();
the_title();
the_content();
endwhile;
?>

3. Сохраняем файл index.php и наслаждаемся результатом.

Описание решения

Первый цикл начинается с очень полезной функции , которая позволяет задавать параметры, используемые в главном цикле. Параметр дает вам возможность указать количество записей. Непосредственно перед циклом мы создаем массив PHP , в котором хранятся все ID записей, используемых в цикле.

Как и первый цикл, второй использует функцию с параметром . Данный параметр позволяет вам определить список записей, которые не нужно выводить, в форме массива PHP. Мы передаем массив в качестве данного параметра. Все записи, полученные в первом цикле, будут пропускаться во втором цикле.

Что такое WP_Query?

— это класс WordPress. Поскольку это именно класс, то из этого следует что у него есть множество свойств, в которых будет храниться нужная нам информация.

Если хотите взглянуть на сам код WP_Query, то его можно найти, открыв файл .

Работа с будет осуществляться в четыре этапа:

  • передача аргументов запроса
  • выполнение запроса
  • прохождение по результату в цикле
  • завершение: сброс данных постов

На практике это будет выглядеть примерно так:

<?php

$args = array(
    // аргументы
);

// Собственный запрос
$query = new WP_Query( $args );

// Проверка на наличие результата
if ( $query->have_posts() ) {

    // Прохождение по результатам в цикле
    while ( $query->have_posts() ) {

        $query->the_post();

    }

}

// Восстановление оригинальных данных
wp_reset_postdata();

?>

Аргументы можно передать непосредственно при создании класса, но я предпочитаю разделять эти вещи.

Сброс данных постов

После каждого запроса необходимо вызывать функцию . Это позволит преобразовать наш запрос в стандартную конфигурацию для вывода контента страницы.

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

Если этого не сделать, то в результате выполнения последующих запросов может быть извлечено не корректное содержимое, что повлияет на условные выражения и многое другое.

Пинги и уведомления

Так же как комментариями, можно управлять пингами. Вот несколько примеров такого управления:

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

Вели вы блог, вели и вдруг пошла нагрузка на сервер через пинги, которые, в общем, никакой практической пользы не несут и которые, очень даже, можно вообще закрыть и забыть о них. Чтобы закрыть все пинги используйте такой SQL запрос.

UPDATE wp_posts p SET p.ping_status = 'closed'
Удаляем все уведомления

Уведомления — это те же пинги — это такие «комментарии», которые оповещают вас о том, что Вася Пупкин сослался на вас. Если вы решили что такие горе-комментарии вам не нужны, их можно удалить оптом, используя такой SQL запрос:

DELETE FROM wp_comments WHERE comment_type = 'pingback';

После удаления пингов логично закрыть возможность получать пинги (см. предыдущий пример), также пинги нужно закрыть в настройках.

Циклы

Без цикла невозможно отобразить контент страницы.

Итак, цикл состоит из следующих этапов:

  • проверяет наличие результата.
  • выполняет внутренний код для каждого поста, полученного в результате выполнения запроса.
  • осуществляет доступ к посту.

Пример рабочего цикла с использованием класса :

<?php

$args = array(
    // аргументы
);

// Собственный запрос
$query = new WP_Query( $args );

// Проверка на наличие результата
if ( $query->have_posts() ) {

    // Прохождение по результатам в цикле
    while ( $query->have_posts() ) {

        $query->the_post();

    }

}

// Восстановление оригинальных данных запроса
wp_reset_postdata();

?>

После цикла следует вызвать функцию .

Создаем главный цикл с помощью объекта WP_Query

Проблема

Классический цикл WordPress, который используется в большинстве вставок кода в данном уроке, является достаточно удобным в применении. Но при задействовании нескольких главных циклов (например, в сложных “журнальных” темах), возрастает риск сбросов, смещений, неправильных тегов и других ошибок.

Решение

Нужно использовать объект и создать свой собственный цикл:

<?php
$myPosts = new WP_Query();
$myPosts->query('showposts=5');

while ($myPosts->have_posts()) : $myPosts->the_post(); ?>
   the_title();
   the_content();
endwhile;

?>

Описание решения

Выше приведенный код выводит пять последних записей. Вот его детальное описание:

  • Строка 2, создаем новый объект с именем .
  • Строка 3, выполняем запрос с параметром для получения пяти последних записей.
  • Строка 5, запуск нашего собственного главного цикла.
  • Строки 6 и 7, выводим информацию из записи (заголовок и ее содержание)
  • Строка 8, завершение нашего главного цикла.

Если вы хотите вывести больше или меньше записей, просто поменяйте значение параметра в строке 3.

Комментарии

Частенько бывает нужно массово закрыть или открыть комментарии или сделать что-то еще с комментариями. Для таких манипуляций можно использовать следующие SQL запросы:

Удаление спам комментариев

Некоторые антиспам плагины, пропускают все комменты, но подозрительные помечают как спам, чтобы, если это не так, потом можно было одобрить комментарий. Например, так делает хваленный Akismet (никогда им не пользовался, он действительно так хорош?). Если спам комментов собралось большое множество, то чистить весь этот мусор руками никак не идет в сравнение с использованием такого простого SQL запроса:

DELETE FROM wp_comments WHERE comment_approved = 'spam'

Если нужно удалить все не одобренные комментарии, используйте:

DELETE FROM wp_comments WHERE comment_approved = 0
Удалим URL у всех комментариев

Чтобы очистить значения поля URL у всех комментариев, можно использовать такой запрос:

UPDATE wp_comments SET comment_author_url=''
Закрыть комментарии в рубрике

Если нужно закрыть комментарии только в какой-то одной рубрике, можно использовать такой SQL запрос, который разом закроет возможность комментирования для всех постов из рубрики, например, (альтернативное название рубрики, слаг):

UPDATE wp_posts p
    LEFT JOIN wp_term_relationships rel ON ( p.ID = rel.object_id )
    LEFT JOIN wp_term_taxonomy tax ON ( tax.term_taxonomy_id = rel.term_taxonomy_id  )
    LEFT JOIN wp_terms tm ON ( tm.term_id = tax.term_id )
SET p.comment_status = 'closed'
WHERE tm.slug = 'stat'

— рубрика в которой мы закрываем комментарии.

Закрыть комментирование в старых постах

Чтобы закрыть возможность оставлять комментарии для старых постов, допустим, опубликованных до 1 января 2010 года, можно использовать такой SQL запрос:

UPDATE wp_posts SET comment_status = 'closed'
WHERE post_date < '2010-01-01' AND post_status = 'publish'

где, как вы догадались, — дата позднее которой комменты будут закрыты.

Удаление комментариев с плохими УРЛами

Можно удалить комментарии по маске, например, если в УРЛе комментатора встречается сочетание букв :

DELETE a,b
FROM wp_comments a
	LEFT JOIN wp_commentmeta b ON ( a.comment_ID = b.comment_id )
WHERE
	a.comment_author_url LIKE '%poker%'
Изменение сайта комментатора

Теоретически УРЛ, который указывает комментатор в поле «сайт» можно изменить при редактировании комментария, но если комментариев этого комментатора много, то везде изменять УРЛ — занятие для обезьянок, проще запросом:

UPDATE wp_comments SET comment_author_url = 'http://example.com'
WHERE comment_author = 'Kama'
AND comment_author_email = 'kama@gmail.com'

Еще один вариант аналогичный предыдущему примеру. Заменит все совпадения на , в УРЛах всех комментаторов:

UPDATE wp_comments
SET comment_author_url = REPLACE( comment_author_url, 'old-site.ru', 'new-site.ru' )
Меняем ID родительского комментария

Иногда пользователи некорректно постят древовидные комментарии — отвечая на коммент не используют кнопку «ответить» в итоге получается, что ответ теряется. Чтобы исправить эту ситуацию можно изменить ID родительского коментария, чтобы правильно расположить новый коммент в дереве:

UPDATE wp_comments SET comment_parent=21 WHERE comment_ID=97

21 — родительский комментарий, 97 — комментарий который нужно поправить.

E-mail’ы комментаторов

Чтобы собрать все мылы комментаторов, например, чтобы сделать какую-нибудь рассылку, можно использовать такой SQL запрос:

SELECT DISTINCT comment_author_email FROM wp_comments

Основные и вторичные запросы

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

Вторичный запрос это тот, который выполняется дополнительно к основному. Например:

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

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

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

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

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

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

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

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

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

Событие pre_get_posts

function my_pre_get_posts( $query ) {
    if ( ! is_admin() && $query->is_main_query() ) {
        $query->set( 'posts_per_page', 5 );
    }
}
add_action( 'pre_get_posts', 'my_pre_get_posts' );

Важно отметить, что вызывается для каждого запроса , включая основной запрос, навигационное меню, вторичные запросы в виджетах и прочее. С помощью метода мы изменяем параметры только основного запроса, а с помощью проверки мы меняем запрос только на лицевой части сайта и не в административной панели

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

Замена текста в записях (постах)

Можно заменить текст в постах и сделать это прямо в Базе Данных. Например можно добавить атрибут ко всем ссылкам с атрибутом :

UPDATE wp_posts SET post_content = REPLACE (post_content, 'rel="nofollow"', 'target="blank" rel="nofollow"')

Еще можно проставить внутренние ссылки с определенным анкором, например, из слова «WordPress» сделать ссылку на какую-нибудь релевантную страницу, чтобы поднять её значимость. В прочем, для этого существуют специальные плагины, которые не трогают текст в БД, а создают ссылки на лету:

UPDATE wp_posts SET post_content = REPLACE (post_content, ' WordPress ', ' <a href="http://example.com/статья-о-wordpress">WordPress</a> ')

Метки

Несмотря на то что WordPress предоставляет достаточно гибкий интерфейс управления метками, вам могут пригодится следующие SQL запросы.

Получаем пустые метки

Спустя несколько лет ведения блога, могут появится пустые метки — метки в которых нет записей. В поздних версиях WP такие метки можно удалить, на странице настроек меток, отсортировав их по количеству записей, а в ранних версиях так отсортировать не получится и для такой операции вам в помощь такой SQL запрос, который получит все метки в которых нет ни одной записи:

SELECT * FROM wp_terms wt
	INNER JOIN wp_term_taxonomy wtt ON wt.term_id=wtt.term_id
WHERE wtt.taxonomy='post_tag' AND
wtt.COUNT=0

Вместо можно написать любую другую таксономию, например категории.

Удаляем пустые метки

В предыдущем примере мы получали пустые метки, а теперь просто удалим их:

DELETE a,b,c FROM wp_terms a
	LEFT JOIN wp_term_taxonomy c ON a.term_id = c.term_id
	LEFT JOIN wp_term_relationships b ON b.term_taxonomy_id = c.term_taxonomy_id
WHERE (
	c.taxonomy = 'post_tag' AND
	c.count = 0
	)

Ну, вы же понимаете, если изменить на , то будут удалены все метки с 0 и 1 записями в них.

Очистка значений метаполей при сохранении

Значение любого метаполя можно очистить через фильтр: sanitize_(type)_meta_(meta_key).

Этот фильтр срабатывает всегда при добавлении или обновлении метаполя.

Все варианты фильтра, если указать первый изменяемый параметр:

  • sanitize_post_meta_(meta_key)
  • sanitize_user_meta_(meta_key)
  • sanitize_comment_meta_(meta_key)
  • sanitize_term_meta_(meta_key)
Пример использования фильтра

Допустим, у нас есть метаполе пользователя my_history (моя история). В это поле пользователь может писать какой-то текст, но в нем нельзя использовать HTML теги. Чтобы быть уверенным наверняка, что туда не попадут эти самые теги, лучше всего очистить значение поля перед сохранением его в базу данных:

add_filter( 'sanitize_user_meta_'.'my_history', function( $meta_value ){
	return wp_strip_all_tags( $meta_value );
});

Получаем запись, опубликованную в промежуток между двумя датами

Проблема

Главный цикл  и функция WordPress WordPress позволяют легко получить список записей, опубликованных в определённую неделю или месяц. К сожалению, вытащить записи, опубликованные, например, после 17 марта и до 3 мая будет не просто. Решим данную задачу.

Решение

Просто скопируйте ниже приведённый код в вашу тему в то место, где нужно выводить список записей, опубликованных между двумя датами. Обязательно поменяйте даты в коде на те, которые нужны вам.

<?php
  function filter_where($where = '') {
        $where .= " AND post_date >= '2009-03-17' AND post_date <= '2009-05-03'";
    return $where;
  }
add_filter('posts_where', 'filter_where');
query_posts($query_string);
while (have_posts()) :
      the_post();
      the_content();
endwhile;

?>

Описание решения

Для решения задачи сначала мы создаем функцию , которая содержит условие SQL “”. Затем перед запуском главного цикла функция будет вызываться функцией WordPress .

В результате условие “”, которое содержится в функции , добавляется в конец запроса SQL, содержащегося в функции . Значит, главный цикл вернет только те записи, которые были опубликованы в период между двумя датами, заданными в функции .

WP_Query PHP код для вывода постов в разделе РЕЙТИНГ

Нижеследующий код выводит все статьи с произвольным полем год, сортируя по этому произвольному полю (от последнего года, до меньшего). Одновременно с этим исключает все записи из категорий меньше значения рейтинга 9.

<?php global $query_string; $paged = get_query_var( ‘paged’, 1 ); $loop = new WP_Query( $args ); $categoryvariable = $cat; $args = array(     ‘post_type’ => ‘post’,     ‘cat’ => $categoryvariable,     // Выводим по произвольному полю     ‘meta_key’ => ‘1Year’,     // Нужен для правильной работы пангинации     ‘paged’ => $paged,     ‘meta_query’=> array(         // Сравниваем поле РЕЙТИНГА с цифрой, меньше которой записи не выводить         ‘key’       => ‘1myRaiting’,         ‘compare’   => ‘>=’,         ‘value’     => 9,         ‘type’      => ‘numeric’,     ),     // Сортируем все записи по годам     ‘orderby’    => ‘meta_value_num’,     // От большего к меньшему     ‘order’      => ‘DESC’,               ); query_posts( $args ); ?>

WP_Query PHP код для вывода записей в разделе ПОИСКА

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

<?php // использую совместно с функцией SearchFilter в Functions.php $mySearch =& new WP_Query(«s=$s & showposts=-1»); // Подсчет количества найденного: $num = $mySearch->post_count; echo «Найдено: «; echo $num; echo «записей»; wp_reset_query(); ?>

Для специальной обработки запроса WP_Query в файле search.php добавляем в файл functions.php своей темы следующий код:

// Сортировка по годам для search.php function SearchFilter($query) {     if ($query->is_search) {         // Ищет только в постах, но не на страницах         $query->set(‘post_type’, ‘post’);         // Происходит сортировка по году         $query->set(‘meta_key’, ‘1Year’);         // Который является значением номера         $query->set(‘orderby’, ‘meta_value_num’);         // И сортируется в обратном порядке         $query->set(‘order’, ‘DESC’);     }     return $query; } add_filter(‘pre_get_posts’,’SearchFilter’);

Он сортирует записи в категории ПОИСК по произвольному полю ГОДЫ.

WP_Query PHP код для вывода постов в КАТЕГОРИИ с БЮДЖЕТОМ

Следующий вывод WP_Query выводит, в категориях WordPress записи, по произвольному полю «Бюджет». В этом поле находятся цифровые значения.

Допустим требуется вывести в категории «Бюджет» все записи, которые будут сортироваться от большей цифры к меньшей.

<?php global $query_string; $paged = get_query_var( ‘paged’, 1 ); $loop = new WP_Query( $args ); $categoryvariable = $cat; $args = array(     ‘post_type’ => ‘post’,     ‘cat’ => $categoryvariable,     // Исключаем категорию     ‘cat’       => ‘-310’,       // Выводим по произвольному полю     ‘meta_key’  => ‘1Budget2’,     // Нужен для правильной работы пангинации     ‘paged’     => $paged,       ‘meta_query’=> array(         // Сравниваем поле бюджет с цифрой, меньше которой записи не выводить         ‘key’       => ‘1Budget2’,         ‘compare’   => ‘>=’,         ‘value’     => 100000000,         ‘type’      => ‘numeric’,         // Сравниваем, что не пустое. Если пустое — то не выводим.         // ‘meta_compare’ => ‘!=’,     ),     // Сортируем все записи по годам     ‘orderby’    => ‘meta_value_num’,     // От большего к меньшему     ‘order’      => ‘DESC’,               ); query_posts( $args ); ?>

WP_Query PHP код для вывода записей в разделе ТЕГОВ

Вывод записей в тегах, в отличии от категорий, немного другой. По какой-то причине, в тегах не работает функция исключающая категории из WP_Query:

‘cat’ => ‘-310’

К счастью, работает другая структура:

‘category__not_in’ => ‘310’

И код вывода $wp_query для тегов будет такой:

<?php // Произвольное поле по которому будет сортировка $the_key = ‘1Year’; $args = array(     ‘meta_key’ => $the_key,     // Сортируем по значению цифры в произвольном поле     ‘orderby’ => ‘meta_value_num’,     // Сортируем от большего к меньшему     ‘order’ => ‘DESC’,     // Исключаем категории     ‘category__not_in’ => ‘310’ ); global $wp_query; query_posts(     array_merge(         $wp_query->query,         $args     ) ); ?>

Добавить комментарий

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

Adblock
detector