Улучшения читабельности WP_Query (для обслуживания)
Работа с WP_Query, особенно когда вы выполняете какую-то нестандартную работу помимо обычного «получить несколько сообщений и отобразить их в шаблоне», может быть полезной. Это особенно верно в отношении некоторых расширенных аргументов (например, использование WP_Meta_Query) .
Также приятно, что настройка процесса имеет стандартный способ ведения дел. А именно:
- Определите аргументы,
- Создайте экземпляр WP_Query,
- Проверьте, есть ли посты,
- Перебери их,
- Закончи их.
Но если вы дойдете до того места, где вы выполняете какую-либо сложную работу, такую как работа с пользовательским типом записи из стороннего решения, загрузка медиафайлов, определение того, существует ли что-то, прежде чем выполнять с ним какую-либо работу, то это может быть проблемой. немного сложнее в работе, не так ли?
Я обнаружил, что, как и во всем в программировании, разбив его на гораздо более удобочитаемые модули (или функции, или части, или как бы вы их ни назвали), можно значительно упростить работу.
Итак, вот один из способов, которым я работаю над улучшением читабельности WP_Query во множестве вещей, которые я делал в последнее время.
Улучшения читабельности WP_Query
Прежде чем перейти к любому примеру, стоит отметить, что есть некоторые вещи, которые мы не можем сделать при настройке WP_Query.
Например, после создания экземпляра запроса мы не сможем делать с ним гораздо более сложные вещи (я имею в виду, что настройка любого модульного тестирования, не требующего ядра WordPress, будет невозможной).
Это лицо того, кто не может следовать вашему кодексу.
С учетом сказанного, вот пример того, как это может выглядеть, когда вы начинаете, а затем как его можно реорганизовать, чтобы иметь меньшие функции, каждая из которых более преднамеренна, чем один длинный метод.
Пример
Допустим, для этого сообщения мне нужно запросить базу данных для всех опубликованных сообщений и сообщений, и я хочу упорядочить их по идентификатору.
Затем я хочу определить, назначил ли какой-либо сторонний инструмент некоторые метаданные, которые соответствуют шаблону, который я могу позже программно назначить для темы, которая у меня есть.
Возможно, первоначальная версия кода могла бы выглядеть примерно так :
<?php
// Assume this is defined within the context of a class.
const MAPPING = [
'employers' => 'page-past-word.php',
'biography' => 'page-biography.php',
'accomplishments' => 'page-csv.php',
];
/* Snip the rest of the class for brevity */
public function map_templates() {
$args = [
'post_type' => array( 'post', 'page' ),
'post_status' => 'publish',
'orderby' => 'ID',
'order' => 'ASC',
'posts_per_page' => -1,
];
$template_query = new WP_Query( $args );
if ($template_query->have_posts()) {
while ($template_query->have_posts()) {
$template_query->the_post();
$template_id = get_post_meta( $post_id, 'third_party_template_id', true );
if ('' === $template_id) {
continue;
}
// The third-party's template post name can be used to map our custom template.
$template_info = get_post( $template_id );
$template_name = $template_info->post_name;
if (isset( self::MAPPING[ $template_name ])) {
$template_file = self::MAPPING[ $template_name ];
update_post_meta( $post_id, '_wp_page_template', $template_file );
}
}
}
}
Это очень много кода, чтобы выполнить довольно много работы для одной функции. По крайней мере, в нем изложено все, что должно произойти, не так ли?
Прежде чем читать дальше, обратите внимание, что массив сопоставления — это всего лишь пример, но ключи представляют собой мета-ключ для его сопоставления, и это помогает нам сопоставить определение значения _wp_page_template, когда придет время сопоставить его с реальными файлами шаблонов WordPress.
Итак, как это можно разбить?
1 Отбросьте все это
Первое, что мы хотим сделать, это создать функцию, которая приводит все это в движение. Есть несколько способов, которыми вы можете это сделать.
Вот как я решил это сделать :
<?php
public function map_page_templates() {
$posts = $this->load_posts_and_pages();
if ($posts->have_posts()) {
$this->assign_templates( $posts );
}
}
Проще говоря, он будет использовать несколько вспомогательных функций, все из которых я задокументирую ниже, а затем назначит любые шаблоны, которые у нас есть в массиве сопоставления, определенном выше.
2 Загрузить сообщения и страницы
Естественно, первое, что мы хотим сделать, это настроить функцию для вызова, которая будет возвращать использование результатов запроса:
<?php
private function load_posts_and_pages() {
$args = [
'post_type' => array( 'post', 'page' ),
'post_status' => 'publish',
'orderby' => 'ID',
'order' => 'ASC',
'posts_per_page' => -1,
];
$posts = new WP_Query( $args );
return $posts;
}
Это возвращает результаты запроса. Таким образом, мы можем определить, нужно ли нам выполнять какую-либо дополнительную работу, о которой мы говорили в сущности на предыдущем шаге:
<?php
public function map_page_templates() {
$posts = $this->load_posts_and_pages();
if ($posts->have_posts()) {
$this->assign_templates( $posts );
}
}
Если нет, то мы закончили. В противном случае, очевидно, мы продолжим.
3 Получите идентификатор стороннего шаблона
Затем идея назначения шаблонов — как показано в приведенном выше коде — кажется достаточно простой, но сначала нам нужно сделать несколько вещей:
- перебирать посты,
- получить сторонний идентификатор шаблона,
- возьмите имя стороннего шаблона,
- назначьте шаблон из константы сопоставления, определенной ранее в классе.
Начальная итерация функции может выглядеть так :
<?php
private function assign_templates( WP_Query $posts) {
while ($posts->have_posts()) {
$posts->the_post();
$template_id = $this->get_template_id( get_the_ID() );
if ('' === $template_id) {
continue;
}
$template_name = $this->get_template_name( $template_id );
if (null === $template_name) {
continue;
}
$this->assign_template( get_the_ID(), $template_name );
}
wp_reset_postdata();
}
Но, как видите, есть еще вспомогательные функции, которым нужны определения. Такие вещи, как возможность получить идентификатор шаблона, имя шаблона и, в конечном итоге, назначить шаблон.
Обратите внимание, однако, что если какая-либо из вспомогательных функций не возвращает полезное значение, мы продолжаем цикл. Это необходимо хотя бы для того, чтобы убедиться, что мы не пытаемся сопоставить несуществующие шаблоны (но я считаю, что это также облегчает чтение).
4 Найдите файл, которому соответствует идентификатор шаблона
Затем можно использовать небольшую функцию для просмотра идентификатора стороннего шаблона и определения, можем ли мы сопоставить это значение со страницами, существующими в нашей базе данных.
<?php
private function get_template_id( $post_id) {
$template_id = get_post_meta( $post_id, 'third_party_template_id', true );
return $template_id;
}
Если это невозможно, то мы можем вернуть пустую строку, а затем вызвать функцию, которая вызвала эту конкретную проверку, чтобы увидеть, стоит ли продолжать цикл, который мы определили.
5 Возьмите имя шаблона
Предполагая, что у нас есть действительный идентификатор сообщения, теперь нам нужно получить имя шаблона из массива сопоставления, определенного ранее в сообщении:
<?php
private function get_template_name( $template_id) {
$template_info = get_post( $template_id );
$template_name = $template_info->post_name;
if (isset( self::MAPPING[ $template_name ])) {
return $template_name;
} else {
return null;
}
}
Вот в чем дело: мы либо вернем имя шаблона, либо вернём нулевое значение. Опять же, это делается для того, чтобы мы могли определить, нужно ли нам продолжать цикл назначения шаблонов или нет.
6 Назначение шаблона
Наконец, мы можем получить идентификатор шаблона, предоставленный третьей стороной, и использовать его для сопоставления с файлом, который мы включили в нашу работу, как описано ранее в посте:
<?php
private function assign_template( $post_id, $template_name) {
$template_file = self::MAPPING[ $template_name ];
update_post_meta( $post_id, '_wp_page_template', $template_file );
}
И именно так вы можете создавать гораздо меньший, более легкий для чтения и простой в использовании код и функции при работе с немного более сложными запросами.
И, таким образом, улучшения читабельности
Для тех, кто привык писать, читать длинные методы или делать что-то так, как большинство учебных пособий в Интернете показывают, как делать что-то в WordPress, это может показаться большим количеством бессмысленного кода.
Но учтите это:
- Более длинные методы труднее читать,
- Их может быть сложнее отлаживать,
- И они не разбивают проблему на более управляемые части.
Конечно, я хотел бы разбить это на еще большее количество классов с их обязанностями, и я считаю, что это можно сделать, но, учитывая природу WP_Query, это потребует немного больше работы.
Поэтому я постарался найти как можно больше золотой середины.
Если вы работаете даже с более сложными вариантами использования WP_Query, я рекомендую хотя бы подумать о том, чтобы разбить его на более мелкие части.
Это помогает позаботиться о читабельности, а возможно, и о ремонтопригодности, а также писать более чистый код, а не один длинный метод со слишком большим количеством условных выражений и зависимостью от множества других данных.