Wp query


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

query_posts() https://codex.wordpress.org/Template_Tags/get_posts

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

WP_Query() https://codex.wordpress.org/Functi on_Reference/WP_Query Для мощной настройки множественных циклов, используйте WP_Query(). Настройкой дополнительных экземпляров WP_Query() в вашем шаблоне можно создать любое количество множественных циклов и настроить вывод каждого из них.

get_posts() https://codex.wordpress.org/Template_Tags/get_posts

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

Разберемся с ними подробнее.

Настраиваем query_posts()

Типичный цикл по умолчанию выглядит вот так:

  

<?php // The WordPress Loop if (have_posts()) : while (have_posts()) : the_post(); ... endwhile; else: ... endif; ?>

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

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

 <?php query_posts('cat=-9'); // исключаем категорию с ID = 9 if (have_posts()) : while (have_posts()) : the_post(); ... endwhile; else: ... endif; ?>

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

 <?php  global $query_string;  $posts = query_posts($query_string.'&cat=-9'); if (have_posts()) : while (have_posts()) : the_post(); ... endwhile; else: ... endif; wp_reset_query(); ?>  

Тег wp_reset_query восстанавливает оригинальный запрос query_posts и используется при применении в шаблонах нескольких последовательных циклов.

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

$posts = query_posts($query_string.'&cat=-7,-8,-9&posts_per_page=3&order=ASC');

что значит вывести 3 записи, исключив 7,8,9 категории и отсортировать записи по алфавиту.

Ключ к успешному использованию query_posts заключается в сохранении оригинального формата запроса с помощью $query_string переменных. Будучи однажды подключенными, можно добавить столько параметров, сколько нужно (подробнее тут https://codex.wordpress.org/Function_Reference/WP_Query#Parameters ).

Этот способ хорош, но не лишен недостатков. query_posts использует дополнительные запросы к базе данных и может повлиять на работоспособность других условных тегов, таких как is_page() и is_ single(). Поэтому рекомендуется не использовать этот способ, хотя он и работоспособен, а заменить его на WP_Query с которым точно проблем не будет.

Настраиваем WP_Query

Для полного контроля над любым количеством циклов, WP_Query – самый лучший способ. Если нужно модифицировать дефолтовый цикл, то это выглядит очень похоже на query_posts:

 <?php // The WordPress Loop - customized with WP_Query $custom_query = new WP_Query('cat=-9');  while($custom_query->have_posts()) : $custom_query->the_post(); ... endwhile; wp_reset_postdata(); // reset the query ?>  

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

 $custom_query = new WP_Query('cat=-7,-8,-9'); // исключить категории $custom_query = new WP_Query('posts_per_page=3'); // ограничить количество $custom_query = new WP_Query('order=ASC'); // порядок сортировки

А также любые нужные комбинации

 $custom_query = new WP_Query('cat=-7,-8,-9&posts_per_page=3&order=ASC');

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

Каждый из этих циклов может быть размещен в любом месте шаблона, не нужно вписывать их последовательно. Например, первый цикл может быть в сайдбаре, второй в футере и т.д.. И каждый выводит свои собственные списки записей, в соответствии с параметрами.

При желании можно комбинировать вместе 3 разных способа query_posts , get_posts и WP_Query в множественных циклах. А в версии вордпресса 3.3 появилась функция is_main_query, позволяющая модифицировать только главные объекты в WP_Query, подробнее на https://codex.wordpress .org/Functi on_Reference/i s_main_query

Настраиваем get_posts

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

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

Но есть один момент, get_posts требует передачи параметров в виде массива, т.е.

Также обратите внимание, что мы используем numberposts вместо posts_per_page для ограничения количества записей. В соответствии с кодексом WP параметр posts_per_page все же должен работать, но если нет — то замените его на numberposts.

Стандартный цикл, а также модифицированные с помощью query_posts и WP_Query поддерживают постраничную навигацию, используя next_posts_link и previous_posts_link, а вот get_posts не поддерживает ее, отображая статический список постов, соответствующих выбранному критерию и все.

Подытожим:

  • Чтобы модифицировать стандартный цикл, используйте query_posts()
  • Чтобы модифицировать иили создать множественные циклы, используйте WP_Query()
  • Чтобы создать статический, дополнительный цикл, используйте get_posts()

Цикл не беспокоится о разметке

Это правда. Можно использовать все, что нам в голову придет. Вот пример типового цикла, закрытого в тег <div>

И вот точно такой же цикл, оформленный в стиле нумерованного списка

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

Обратите внимание, что не только разметка отличается в этих трех примерах, но и используемые функции разные. Например, в третьем случае использовался the_excerpt() для вывода цитат вместо контента.

По умолчанию the_excerpt() выводит первые 55 слов записи, если не задано поле цитата записи. Поэтому для постов длиной меньше 55 слов будет выведено полное содержание, более 55 слов – только часть.

Мораль такая — циклы WordPress очень удобная, гибкая и мощная штука — вы можете как угодно применять их и где угодно размещать.

Мощь WP_Query

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

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

Как и в предыдущих примерах, изменением параметров в новом WP_Query вы легко настраиваете вывод любого набора записей. Давайте подробно разберем наиболее типичные способы применения.

Отображение разного количества записей

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

Таким образом мы ограничим количество выводимых постов шестью, вместо десяти (значение по умолчанию). Чтобы вывести абсолютно все записи, нужно указать параметр равный «-1».

Исключаем некоторые категории

Одна из самых популярных задач – исключение записей определенной категории на главной странице сайта. Например, у вас есть несколько записей про хомячков, но вы хотели бы убрать их с главной страницы сайта. Этот контент остается в базе данных, отображается в своей рубрике и RSS ленте, но только не на главной. Есть множество способов сделать это, но мы применим самое простое из решений…да, это WP_Query class:

В общих случаях, знак минус означает исключить данный параметр.

Поэтому мы исключили третью рубрику (про хомячков).                                                   

Другие возможности исключить содержимое этой рубрики — использовать php функцию continue и пропускать записи определенной категории, скрывать контент с помощью css и javascript, править файлы ядра вордпресс и использовать плагины. Согласитесь, WP_Query однозначно лучше.

Изменяем порядок сортировки

WordPress относится к приложениям LIFO типа — last in, first out, т.е. последний пришел, первый вышел. Что означает, что мы видим сначала свеже опубликованные записи, а старички спрятаны глубоко в недрах навигации. Это рационально, т.к. большинство блоговых сайтов стремится первым показать самый свежий контент. Это дает людям смысл периодически возвращаться на сайт, т.к. они смогут найти что-то новенькое прямо на первой странице сайта. Но это не идеальный вариант для каждого типа сайтов.

Допустим, вы используете вордпресс для того, чтобы публиковать свой роман. Это означает, что вы писали и публиковали его хронологически, главу за главой. Поэтому, когда посетители приходят на ваш сайт, вы хотите показать им сначала главу Один, но она является фактически самой старой записью, поэтому вместо этого они увидят самую последнюю опубликованную главу. Но нет проблем, всего навсего изменим порядок сортировки:

Покажем специфические страницы, встраивая страницу в страницу

Другой интересный и полезный цикл, это использовать новый WP_Query class для отображения только одной определенной страницы. Это может быть полезно из разных соображений, например, для встраивания одной страницы в другую. Вот пример запроса, когда содержимое страницы About встраивается в другую страницу:

Обратите внимание, что в pagename нужно использовать не реальное название страницы, а ее слаг.

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

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

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

Таким образом у нас получается 4 цикла

1 — Левый сайдбар 2 — Левая колонка 3 — Правая колонка 4 — Правый сайдбар

new WP_Query( 'cat=7&showposts=3');

3 последние записи из рубрики номер 7

new WP_Query( 'cat=-7&showposts=5');

5 последних записей, кроме из рубрики номер 7

new WP_Query( 'cat=-7&showposts=5 &offset=5');

еще 5 последних записей, кроме из рубрики номер 7

new WP_Query( 'cat=-7&showposts=10 &offset=10');

еще 10 последних записей, кроме из рубрики номер 7

которые будут находиться в index.php, но также разместить их можно будет где угодно еще.

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

Параметр cat

  • Цикл 1 — отображает записи только из 7 рубрики (cat=7)
  • Цикл 2 — отображает записи кроме 7 рубрики (cat=-7)
  • Цикл 3 — отображает записи кроме 7 рубрики (cat=-7)
  • Цикл 4 — отображает записи кроме 7 рубрики (cat=-7)

Параметр showposts

  • Цикл 1 — отображает только 3 записи (showposts=3)
  • Цикл 2 — отображает только 5 записей (showposts=5)
  • Цикл 3 — отображает только 5 записей (showposts=5)
  • Цикл 4 — отображает только 10 записей (showposts=10)

Параметр offset

  • Цикл 1 — не используется Цикл 2 — не используется
  • Цикл 3 — пропускает первые 5 записей (offset=5)
  • Цикл 4 — пропускает первые 10 записей (offset=10)

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

Для этого примера мы создадим навигацию на предыдущие и следующие записи в втором цикле. А также настроим отображение полных записей или цитат записей в нужных местах.

Цикл 1 — Левый сайдбар

Отображает 3 кратких записи.

Цикл 2 — Левая колонка

Отображает 5 полных записей, а после них выводит ссылки на следующие и предыдущие записи.

Цикл 3 — Правая колонка

Цикл 4 — правый сайдбар

Отображает 10 полных записей.

Понятно, что стоит добавить нужные html коды верстки и разметки для создания стиля и структурирования отображения контента, но уже этого кода почти достаточно для создания своего собственного шаблона.

iwsm.ru

Как создать продвинутый поиск в WordPress с помощью WP_Query

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

Большая часть преимуществ WordPress идет из его гибкой архитектуры данных, с помощью которой разработчики могут широко настраивать свои системы с помощью пользовательских типов постов, таксономий, а также пользовательских полей. Однако когда речь заходит о поиске в WordPress, то пользователю предоставляется всего одно поле, которое зачастую ведет себя настолько неадекватно, что администраторы загружают внешние поисковые системы наподобие Google Custom Search или сторонних плагинов.

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

Запросы пользователя

Когда пользователь переходит по ссылке или вбивает URL определенной страницы вручную, WordPress выполняет серию операций, хорошо описанную в Query Overview. Если коротко, то происходит следующее:

Первым происходит парсинг URL строки, так что давайте разберем строки запроса и переменные.

Переменные WP Query: стандартные и пользовательские

В кодексе говорится: «Пользователи или разработчики WordPress могут использовать массив переменных запроса для поиска контента определенного типа или в качестве дополнительного функционала в дизайне темы и/или плагина.»

Другими словами, переменные запроса WP определяют результат выполнения запроса в БД. По умолчанию в WP доступны переменные запроса типа private и public. В кодексе о таких переменных говорится: Публичные переменные запроса это переменные, доступные напрямую через URL запроса из формы. example.net/?var1=value1&var2=value2

Приватные переменные нельзя использовать в URL строке. WP принимает строку запроса с приватными переменными, но они не пройдут парсинг. Поэтому такие переменные необходимо указывать напрямую в запросе. Пример ниже.

И как следствие, через строку запроса нельзя послать такие приватные переменные, как category__in, category__not_in, category__end и т.д (в кодексе вы найдете полный список встроенных переменных, которые можно использовать в строке запроса).

С помощью публичных переменных мы (как пользователи или разработчики) можем составить довольно много запросов, и нам не понадобится создавать плагины или редактировать файл темы functions.Нам нужно всего лишь создать URL, добавить к строке запроса пару доступных параметров, и WP покажет пользователю страницу с результатом.

В качестве примера с помощью параметра post_type в строке запроса мы можем получить посты определенного типа; или мы можем произвести поиск по пользовательской таксономии, добавив в конец строки запроса пару taxonomy-name=taxonomy-term. К примеру, можно создать следующий URL: mywebsite.com/?post_type=movie&genre=thriller

WP обратиться к базе данных и вытянет все посты типа movie с жанром thriller, где genre – пользовательская таксономия. Круто, но это не все. До сих пор мы говорили только о встроенном функционале переменных запроса, однако WordPress так устроен, что мы можем создавать свои собственные переменные запроса.

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

Пользовательские переменные необходимо зарегистрировать перед использованием. Сделать это можно с помощью фильтра query_vars. Давайте откроем главный файл плагина (или файл темы functions.php) и пропишем там код ниже:

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

Теперь можно добавить наши новые переменные в параметры строки запроса. Благодаря get_query_var() эти параметры будут доступны в нашем скрипте, это мы увидим чуть позже. А сейчас настало время познакомить вас с классом, который управляет запросами в WordPress.

Ее величество WP_Query

Запрос в базу данных – задача не из простых. Главное не просто создать точный запрос, а создать запрос таким, чтобы в нем не было дыр в безопасности. С помощью WP_Query Class мы можем получить быстрый и безопасный доступ к БД WordPress (WP_Query строит безопасные запросы в фоновом режиме).

С помощью множества методов и свойств класса полученные из БД данные попадают в цикл Loop. Разберем базовый пример с Loop:

Если вы еще новичок в WordPress разработке, вы можете задаться вопросом: «А где, собственно, сам запрос?!». По факту, вам не нужно создавать новый экземпляр объекта WP_Query. Класс сам создает запрос для запрошенной страницы. Так что если пользователь захотел просмотреть посты по определенной категории из архива, WP создаст запрос и вытянет все посты по определенной категории, а Loop покажет их.

Но это самый простой пример основного запроса. Передав в новый экземпляр класса WP_Query массив с параметрами, мы можем расширить этот функционал и фильтровать результат. В примере ниже показано, как это сделать:

Выглядит немного сложнее, не так ли? Однако если рассмотреть код поближе, это не так. В новом объекте класса WP_Query хранится массив аргументов, который влияет на то, какие данные мы вытянем из БД. В кодексе можно найти полный список параметров, сгруппированных в 17 категорий. К примеру, там есть параметры автора, категорий, один параметр поиска (s), параметры пользовательских полей и т.д. (чуть позже мы вернемся к параметрам WP_Query).

После создания объекта $query нам доступны все его методы и свойства. Методы have_posts проверяет, остались ли еще посты для вывода, а the_post передвигает Loop к следующему посту и обновляет глобальную переменную $post.

При создании пользовательского запроса всегда необходимо вне цикла Loop вызывать wp_reset_postdata(). Эта функция восстанавливает глобальную переменную $post после выполнения пользовательского запроса. Это крайне важно, т.к. любой новый запрос перезаписывает переменную $post. Из кодекса:

«Обратите внимание: Если в своем запросе вы используете the_post(), после запроса вам понадобится запустить метод wp_reset_postdata(), чтобы Template Tags снова использовали основной запрос текущего поста.»

Вернемся к аргументам запроса.

Аргументы WP_Query

Мы уже сказали, что в классе WP_Query хранится массив параметров, с помощью которых разработчики могут выбирать, что вытянуть из БД.

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

Если нужно получить все посты от автора по имени carlo, необходимо прописать следующий запрос:

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

Если нужно получит все посты по категории webdesign, необходимо просто задать аргумент category_name, как показано ниже:

Запрос ниже ищет все посты по двум категориям, запятая здесь заменяет OR:

Также можно искать посты, принадлежащие к обеим категориям webdesign и webdev, для этого необходимо поставит знак + между ними, он равносилен AND:

Также можно передать массив с ID:

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

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

Мета-запросы WordPress

В кодексе говорится, что при работе с мета-зпросами WP_Query использует класс WP_Meta_Query. Данный класс впервые появился в WordPress 3.2 и строит SQL код запросов на основе пользовательских полей. Чтобы построить запрос на основе всего одного пользовательского поля, нам потребуется один или более аргументов:

Допустим, пользовательский тип постов называется accommodation. Давайте присвоим каждому accommodation пользовательское поле city, в котором будет храниться географическое местоположение. С помощью мета-запроса мы можем вытянуть из БД все посты по типу accommodation с определенным городом. Для этого нужно всего лишь передать нужные аргументы в запрос, как показано ниже:

После создания аргументов можно строить запрос, как мы уже это делали раньше:

Вставьте код выше в файл шаблона и вы получите архив всех постов с типом accommodations, написанных в городе Freiburg.
Это был пример с одним пользовательским полем. А что, если нам нужно построить запрос на основе нескольких пользовательских полей?

meta_query аргумент

Для такого запроса в классе WP_Meta_Query есть параметр meta_query. Это массив массивов:

Параметр meta_query – это двумерный массив, чьи ячейки являются отдельными мета-запросами со следующими аргументами:

Wp query

Если задать более одного пользовательского поля, нам потребуется назначить элементу meta_query аргумент relation. После всего этого мы можем построить более продвинутый запрос. Начнем с создания аргументов и нового объекта WP_Query:

Здесь в аргументе meta_query хранится два массива с мета-запросами, а третий параметр устанавливает связь между запросами. Запрос просеивает таблицу wp_posts на все посты типа accommodation с пользовательскими полями city = «Paris» и type = «room».

Скопируйте код выше в файл шаблона archive-accommodation.php. При запросе с данными параметрами WP произведен поиск в таблице wp_posts, а Loop покажет доступные результаты.

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

Фильтр pre_get_posts

Экшен pre_get_posts запускается после создания объекта $query, но перед его выполнением. Чтобы модифицировать запрос, нам придется прикрепить свою колбэк функцию pre_get_posts.

В одном из предыдущим примеров мы вытягивали все посты заданного автора с категорией webdesign. А в примере ниже мы будем передавать те же аргументы в объект $query, однако на этот раз мы не будем это делать в файле шаблона, а используем основной файл плагина (или файл темы functions.php). Напишем следующий блок кода:

Объект $query передается в колбэк функцию не по значению, а по ссылке, что означает, что любые изменения в запросе напрямую влияют на объект $query. В кодексе говорится:

«С помощью экшена pre_get_posts разработчики могут обращаться к объекту $query по ссылке (любые изменения в $query напрямую влияют на оригинальный объект – возвращать значение не обязательно).»

Так как мы манипулируем исходным объектом $query, нужно смотреть, с каким запросом мы работаем. Метод is_main_query проверяет, является ли объект $query основным запросом. В кодексе также говорится, что фильтр pre_get_posts может повлиять как на панель администратора, так и на front-end страницы. Поэтому крайне рекомендуется проверять запрашиваемую страницу с помощью условного тега is_admin.

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

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

От теории к коду: создаем поисковую систему

Нам потребуется:

Создаем структуру данных

Цель постов пользовательского типа в том, чтобы добавить контент, который нельзя логически включить в посты блога или статические страницы. Пользовательские типы постов особенно подходят для показа событий, товаров, книг, фильмов, каталогов предметов и т.д. Мы создадим архив объявлений о недвижимости по следующей структуре:

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

Wp query

Страница редактирования поста типа accommodation, справа показаны все пользовательские мета боксы и поля. На рисунке видно, как будет выглядеть сраница Edit Accommodation с тремя пользовательскими мета боксами, в которых хранится таксономия Typology и несколько зарегистрированных полей.

Наша цель не анализировать архитектуру данных WP, это за нас уже сделали пользователи сайта Smashing Magazine Daniel, Brian, Kevin, Josh и Justin. Если вам нужно освежить знания, можете прочесть их статьи и вернуться к моей. После создания архитектуры данных необходимо зарегистрировать переменные запроса.

Регистрация переменных запроса

В предыдущей части мы узнали, что переменные запроса это пара key=value после знака вопроса в строке URL. Однако перед тем, как мы сможем обработать эти пары в нашем скрипте, необходимо их зарегистрировать в плагине или файле functions.php. Нам понадобятся всего две переменные, с помощью которых мы сможем выполнять запрос на основе значений соответствующий пользовательских полей:

Вот и все! Мы добавили два дополнительных параметра в запрос к БД. Теперь необходимо написать URL типа: http://example.com/?type=XXX&city=YYY

Манипуляция запросом

Добавьте новый кусок кода в наш скрипт:

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

Далее функция проверяет доступность ранее зарегистрированных переменных запроса. Проверка осуществляется при помощи функции get_query_var, которая вытягивает публичные переменные запроса из HTTP запроса (более подробно о get_query_var прочтите в кодексе). Если хоть одна переменная существует, колбэк функция создает по массиву на каждый мета-запрос и помещает их в многомерный массив $meta_query.

Если доступно хотя бы два мета-запроса, то к $meta_query добавляется аргумент relation со значением «AND». После этого метод set сохраняет $query для его последующего исполнения.

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

Создание формы поиска

Данные из формы отправляются методом GET, а значит, атрибуты полей формы name и value отправляются как переменные в URL (т.е. переменные запроса). Поэтому мы зададим атрибутам name полей формы те же значения, что и в ранее зарегистрированных переменных запроса (city и type), а значения самих полей могут быть назначены программно с помощью данных из БД или ручного ввода пользователя.

Сперва мы создадим шорткод, с помощью которого админы смогут подключить форму поиска к постам и страницам сайта. Наш шорткод подсоединяется к экшену init:

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

$args – массив атрибутов шорткода. Внутрь функции мы добавим:

Мы создали запрос, который вытягивает все посты типа accommodation с заданным кастомным полем _sm_accommodation_city (подчеркивание перед именем означает скрытое пользовательское поле).

Цикл Loop не покажет посты типа accommodation, но добавить элементы соответствующего значения пользовательского поля в массив $cities. По условию дубликаты будут пропускаться. Если нет ни одного поста типа accommodation, функция прекращается; в противном случае элементы массива сортируются и используются для вывода значений первой группы тегов option в выпадающем списке.

Wp query

Все доступные города в выпадающем списке. Второе поле формы это выпадающий список кастомной таксономии typology. Значения второй группы тегов option выводятся с помощью get_terms. Код ниже генерирует поле select для таксономии typology:

get_terms возвращает массив всех терминов набора таксономии в качестве первого аргумента или в виде объекта WP_Error, если таксономия не существует. И цикл foreach выводит теги option выпадающего списка.

Wp query

Варианты второго выпадающего списка. Осталось последнее поле select, которое будет относиться к пользовательскому полю type. Код:

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

Мы создали скрытое поле для публичной переменной запроса post_type. Когда пользователь отправляет форму, WP получает значение post_type и загружает файл шаблона archive.php или если есть archive-{post_type}.php. Если вы будете настраивать HTML структуру страницы с результатами, для такой формы понадобится специальный файл шаблона.

Wp query

На изображении показана форма продвинутого поиска, которую мы создали в этой статье.

Поиск по любому тексту

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

Благодаря текстовому полю мы можем передать в WP_Query новую пару ключ/значение, где ключ это параметр s, а значение это текст, введенный пользователем или возвращаемое значение функции get_search_query() (более подробно в кодексе).

Wp query

Более расширенная поисковая форма. Последнее замечание: в предыдущем примере мы видели, как WP загружает файл шаблона архива для показа результата запроса. Это происходит потому, что мы не задали аргумент поиска. Когда в строке запроса есть параметр s, WP автоматически загружает файл шаблона страницы поиска, как показано на последнем изображении ниже.

Wp query

Заключение

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

Автор: Carlo Daniele

Источник: https://www.smashingmagazine.com/

Редакция: Команда webformyself.

Wp query

webformyself.com

About The Author

Hello, I’m Daniel and I make things for the web. I’m the CTO at Kinsta and I write for a number of amazing publications like Smashing Magazine and … More about Daniel

  • Leave a comment
  • 9 min read
  • WordPress, Themes, Techniques (WP)
  • Share on Twitter or LinkedIn

If you’ve been around WordPress for a while you know how difficult it used to be to create post lists based on complex criteria while also conforming to WordPress standards. Over the course of a few years the platform has come a long way. By utilising the power of the WP_Query class, we can lists posts in any way we want.

If you’ve been around WordPress for a while, you’ll know how difficult it used to be to create lists of posts based on complex criteria while also conforming to WordPress’ standards. Over the course of a few years, the platform has come a long way. By using the power of the WP_Query class, we can lists posts in any way we want.

wp_query

What Is WP_Query?

The WP_Query class is one of the most important parts of the WordPress codebase. Among other things, it determines the query you need on any given page and pulls posts accordingly. It also saves a lot of information about the requests it makes, which helps a great deal when optimizing pages (and troubleshooting them).

The other role of WP_Query is to enable us to perform complex database queries in a safe, simple and modular manner.

Further Reading on SmashingMag:

  • Powerful WordPress Tips And Tricks
  • Building An Advanced WordPress Search With WP_Query
  • 10 Useful WordPress Loop Hacks
  • Do-It-Yourself Caching Methods With WordPress

Safety

Throughout our interactions with this object, we are supplying parameters and using functions to reach our goal. The object’s internals take care of many annoyances, such as protecting against SQL injection attacks and making sure that proper data types are used.

Simplicity

The object abstracts much of the query complexity away so that we don’t have to muck about with the specifics of our database. Because we are using an array to supply our criteria, everything is more self-explanatory. No manual database joins or nested queries are needed — just create an arguments array and instantiate the class!

Modularity

My favorite of all is modularity. When making raw queries, it is hard to manage those frequently used bits because they are just fragments of SQL code. WP_Query does away with this by using an associative array as an argument. A plethora of goodness ensues: you can merge arguments from different places, run array functions to your heart’s content and manipulate it in ingenious ways.

Getting Started

The “Regular” WordPress Loop

Let’s look at a regular loop first, and then create the same loop using WP_Query. Let’s assume that we’re coding in the category.php file.

The Same Loop Using WP_Query

As you can see, there is not much difference at all! Let’s break it down:

  1. Constructing a query On a category page, WordPress already knows that you want to list posts from that category. Because we are constructing a query from scratch using WP_Query, we need to specify this ourselves. We’ll delve a bit deeper into this in a bit.
  2. Instantiating the class and querying for posts By instantiating a class with the constructed argument array, WP_Query will try to pull the posts specified and a load of other details.
  3. Creating a loop You can use all of the usual functions; just be sure to use them as the methods of your object:
    • Instead of have_posts(), use $category_posts->have_posts().
    • Instead of the_post(), use $category_posts->the_post().
  4. Resume business as usual Once you’ve done the above, you can use all of the template tags you’ve come to know and love.

If you look at this in detail, you will find that the global $post object is also available. This means that if you use a custom loop like this within another loop, things can go wrong. Be sure to store the original value of the $post object and restore it after the loop.

Digging Deeper

The Power of a Good Argument

The ease with which we can create loops is obvious, but what about actually querying for posts? Let me show you a common technique I use when creating sliders for commercial themes.

In many cases, users of your theme will want a great-looking slider, but they might be a bit lazy in creating content. Many users will also want to show future content. Let’s query for upcoming (i.e. unpublished) posts that have an attached featured image.

Short, sweet and utterly understandable — just beautiful. And we’ve just scraped the surface.

Know Your Defaults

You may have noticed that I didn’t specify a number of things in my queries. What about how many posts to list? What about the post’s status in the first query we made?

Default values are supplied for many of the most common arguments. Here are a few that you don’t have to specify, unless you want to change them:

  • posts_per_page Defaults to the value specified in the reading settings for the number of posts to list.
  • post_type Defaults to post.
  • post_status Defaults to publish.

You can find the complete list of parameters in the Codex, of course!

Arrays Are Awesome

In many cases, you will want to specify a number of values that an argument can take. Where it would seem logical, WP_Query usually allows you to use arrays to make your life easier. Here are a few examples:

  • You can use an array for post_status to pull posts from a number of different statuses. Note that you can use the string any to get posts from all statuses.
  • If you use custom post types, you’ll be happy to hear that you can use an array for the value of the post_type parameter as well.
  • For the taxonomy type parameters category__in, tag__in and so on, you can use an array to indicate a multitude of values.

Handling Taxonomies

WP_Query is nice enough to offer a simple way to make advanced taxonomy queries as well. This is especially useful for websites with complex set-ups and for commercial themes with large feature sets. The mechanism used is called tax_query. Let’s look at an example.

Say you have a website all about movies. You store movies in a custom “movie” post type; you have a custom taxonomy for genre, a custom taxonomy for actors, and you use the regular ol’ category to indicate how good a movie is. Let’s find all “Action” movies starring “Bruce Willis” that aren’t “Bad”:

While this hardcoded example would be useful only to people who love Die Hard, it’s not hard to see how an advanced filter can be built that lets users filter through your content in any which way they want.

Learn more about all of the awesome things you can do with the taxonomy parameters in the Codex.

Having Fun With Meta Data

You’ve already seen that WP_Query is great at handling meta data — we used a meta_query in the second example to build a slider from posts that have featured images. Just as with the taxonomy queries, a lot of flexibility is built in here.

We’re currently building a WordPress theme to be used to create a Web page for apartment(s) for rent. We store apartments as a custom post type and use meta data to store the details. With a meta query, we can easily pull in all apartments that can house four or more people, that have a balcony and that are non-smoking.

Again, this is very modular, very understandable. To learn more about the parameters you can use, just visit the “Custom Field Parameters” section in the WP_Query documentation.

Methods And Properties

Once you’ve made a query, you can coax a lot of information out of your object. You can find a full list of “Methods and Properties” in the Codex. Here are the ones I tend to use most:

  • $query Shows you the query string passed to the $wp_query object. This is quite helpful for troubleshooting in some advanced cases.
  • $query_vars Shows an associative array of the arguments you’ve passed. If you do plenty of mixing and matching before passing arguments, this tool could be helpful indeed to check that all is well.
  • $posts Holds the requested posts from the database. I rarely use this property, but it’s good to know that this is where your items come from.
  • $found_posts A handy little thing that shows the total number of found items (without the limit imposed by the posts_per_page argument).

With Great Power Comes Great Responsibility

While WP_Query gives you plenty to play around with, it does have its drawbacks. Many people (my past self included) go nuts when they realize how easy it is to bang out queries all over the place.

Keep in mind that more queries mean more server load. I’ve found that on hosted systems, complex queries can be especially naughty because they eat at your RAM, which is probably your scarcest resource.

Make sure to check out what the default query holds on each page. What’s the sense in creating a new query for the latest posts on the front page if it’s there by default? Use what you can more than once, cache results, and so on.

www.smashingmagazine.com

Использование WP_Query в WordPress

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

Что такое WP_Query?

Класс WP_Query является одной из важнейших частей в движке WordPress. Среди прочего, он определяет запросы, которые вам необходимы на любой странице и выводит сообщения в соответствии с заданными критериями. Он также сохраняет много информации о запросах которые делает, что помогает при оптимизации страниц (и устранении ошибок).

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

Безопасность

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

Простота

При использовании этого объекта нам не нужно изучать особенности нашей базы данных. Поскольку мы используем массив, чтобы передавать наши параметры, нет нужды вручную писать запросы с join или вложенные запросы, нужно просто создать массив аргументов и экземпляр класса!

Модульность

WP_Query позволяет избежать использования SQL-запросов в коде, класс использует ассоциативный массив в качестве аргумента. Это позволяет получить множество преимуществ: вы можете объединить аргументы из разных мест кода, запустить массив функций и управлять ими всевозможными способами.

Итак, начнем!

«Стандартный» цикл в WordPress

Давайте посмотрим вначале на обычный цикл, и затем создадим такой же цикл, используя WP_Query. Давайте предположим, что мы создаем файл category.php для своей темы.

То же цикл, используя WP_Query:

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

Построение запросов

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

Создание экземпляра класса и запросов для сообщений

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

Создание цикла

Вы можете использовать любые обычные функции, только не забудьте использовать их в качестве методов объекта:

Вместо have_posts(), используйте $category_posts->have_posts().
Вместо the_post(), используйте $category_posts->the_post().

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

Если вы посмотрите на это подробнее, то вы увидите, что глобальный объект $post также доступен. Это означает, что если вы используете пользовательский цикл, что-нибудь может пойти не так. Обязательно сохраните первоначальное значение объекта $post и восстановите его после цикла.

Идем дальше…

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

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

Короткий и совершенно понятный код — просто и красиво.

Значения по умолчанию

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

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

posts_per_page
По умолчанию используется значение, указанное в параметрах сайта о количестве сообщений на странице.

post_type
По умолчанию используется post.

post_status
По умолчанию используется publish.

Вы можете найти полный список параметров в документации!

Массивы

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

Вы можете использовать массив для post_status, чтобы получить сообщения с различными статусами. Обратите внимание, что вы можете использовать строку any, чтобы получить сообщения со всевозможными статусами.

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

Для таксономии параметры типа category__in, tag__in и так далее, вы можете использовать массив для указания множества значений.

Обработка Таксономии

WP_Query достаточно хорош, чтобы предложить простой способ сделать сложные запросы к таксономии. Это особенно полезно для веб-сайтов с сложными  настройками для коммерческих тем и с большим набором функций. Используемый механизм называется tax_query. Давайте посмотрим на примере.

Скажем, у вас есть сайт: Все о кино. Вы храните фильмы в пользовательском типе записей «movies»; у вас также есть тип записей для жанра, пользовательский тип записей для актеров, и вы используете обычную категорию, чтобы указать, насколько хороший фильм. Давайте найдем все фильмы жанра «Action» в главной роли с Брюсом Уиллисом, которые не являются «Bad»:

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

Узнать больше о использовании параметров таксономии можно в соответствующем разделе документации.

Работаем с метаданными

Вы уже видели, что WP_Query отлично справляется с мета-данными — мы использовали meta_query во втором примере, когда строили слайдер с записями, которые имеют изображения.

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

Чтобы узнать больше о параметрах, которые можно использовать, просто зайдите в раздел Custom Field Parameters в документации по WP_Query.

Методы и свойства

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

$query
Показывает строку запроса, которая передается в объект $wp_query. Это очень полезно для устранения неполадок в некоторых случаях.

$query_vars
Показывает ассоциативный массив аргументов, которые вы передали. Если вы делаете много смешиваний и сопоставлений перед передачей аргументов, этот инструмент может быть полезным, чтобы проверить, что все передано правильно.

$post
Содержит запрошенные записи из базы данных.

$found_posts
Удобная вещь, которая показывает общее число найденных элементов (без ограничения установленного аргументом posts_per_page).

С большой силой приходит большая ответственность

WP_Query дает вам большие возможности, но у него есть свои недостатки. Многие люди «сходят с ума», когда они понимают, как легко можно вызывать запросы повсюду.

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

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

Перевод статьи с http://wp.smashingmagazine.com

www.webmasters.by


You May Also Like

About the Author: admind

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

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

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.