TL;DR: в этой статье описывается код, необходимый для добавления пользовательской ссылки на экран «Все сообщения », которая использует пользовательский фрагмент метаданных сообщения.
Примечание. Несколько месяцев назад я написал статью о том, как добавить пользовательский вид на экран «Все сообщения ». Эта статья не все вместе то же самое, но и не все вместе разные. Думайте об этом как о более подробном и, возможно, более практическом воплощении концепции.
Предположим, что у вас есть стандартный тип записи или пользовательский тип записи, и вы собираетесь просто фильтровать по заголовку, который вы определяете, используя механизм, позволяющий сохранять данные в post_metadataтаблицу.
Например, предположим, что у вас есть сообщение и оно представляет собой часть метаданных с:
- а
meta_keyсо значениемarticle_attribute - а
meta_valueсо значениемheadline
И вы хотите использовать эту информацию, чтобы добавить новую ссылку «Заголовки », которая автоматически отфильтровывает все, кроме статей с этими метаданными.
Вот как это сделать.
Пользовательская ссылка на экране всех сообщений
Прежде чем начать, стоит отметить, что есть два способа решить эту проблему:
- Мы могли бы сначала добавить ссылку в верхней части страницы «Все сообщения », а затем добавить функциональность для фильтрации данных,
- Или мы можем сделать это наоборот, сначала добавим внутреннюю логику, а затем добавим ссылку на страницу «Все сообщения ».
Я собираюсь начать со второго варианта. Нет причин, почему это должно быть сделано именно так. Это мое предпочтение.
Во-первых, мне нужно подключиться к [pre_get_posts](https://developer.wordpress.org/reference/hooks/pre_get_posts/)хуку, предоставленному WordPress. Я не собираюсь использовать в этом примере какие-либо классы с именами или префиксные функции (учитывая, что я достаточно рассмотрел этот контент на этом сайте), но у меня будет демонстрационный плагин для этого, связанный внизу сообщения.
В любом случае, я начну с добавления анонимной функции, прикрепленной к вышеупомянутому хуку:
add_action(
'pre_get_posts',
function (WP_Query $query) {
}
);
Обратите внимание, что анонимная функция принимает единственный аргумент, который является ссылкой на текущий экземпляр WP_Query, работающий на странице. Если вы не знакомы с этим классом, я рекомендую прочитать любую из этих статей или страницу ресурсов для разработчиков .
В функции мне нужно проверить наличие a meta_valueв строке запроса. Это легко сделать благодаря [filter_input](https://www.php.net/manual/en/function.filter-input.php)функции, предоставляемой PHP.
add_action(
'pre_get_posts',
function (WP_Query $query) {
$meta_value = 'headline';
if (filter_input( INPUT_GET, 'meta_value') === $meta_value) {
$query->set( 'meta_key', 'article_attribute' );
$query->set( 'meta_value', $meta_value );
}
}
);
Этот хук будет проверять, является ли headlineзначение ключом для meta_valueключа в строке запроса. Если это так, то он добавляет meta_keyи meta_valueк экземпляру WP_Queryкоторого WordPress будет получать все сообщения только с этими метаданными.
После этого мне нужно добавить ссылку вверху страницы «Все сообщения », чтобы активировать эту функцию. Для этого я использую [views_edit-posts](https://tommcfarlin.com/add-a-custom-view/)крючок. Эта функция примет массив якорей, которые будут отображаться в верхней части страницы.
Я ссылаюсь на них как $viewsна то, что функция примет, когда я ее заглушу:
add_action(
'views_edit-post',
function (array $views) {
return $views;
}
);
Обратите внимание, что важно вернуть массив обратно в WordPress, чтобы он знал, что отображать, даже если не было сделано никаких изменений.
Во-первых, мне нужно определить, нахожусь ли я в данный момент на пользовательской странице. Если это так, то мне нужно добавить соответствующие атрибуты к якорю, добавленному в верхнюю часть страницы:
$attributes = 'class=""';
if (filter_input(INPUT_GET, 'meta_value') === 'headline') {
$attributes ='class="current aria-current="page"';
}
После этого мне нужно добавить на страницу представление «Заголовки ». Для этого потребуется использование нескольких функций:
[array_push](https://www.php.net/manual/en/function.array-push.php)за добавление новой ссылки в список$views[sprintf](https://www.php.net/manual/en/function.sprintf.php)для безопасного добавления новой строки[add_query_arg](https://developer.wordpress.org/reference/functions/add_query_arg/)для добавления набора настраиваемых аргументов запроса на текущую страницу.
Следующий участок кода будет выглядеть так:
array_push(
$views,
sprintf(
'<a href="%1$s" %2$s>%3$s
<span class="count">(%4$s)</span>
</a>
',
add_query_arg([
'post_type' => 'post',
'post_status' => 'all',
'meta_value' => 'headline',
], 'edit.php'),
$attributes
__('Headlines'),
count( );
);
Но я еще не закончил. Обратите внимание, что я вызываю [count](https://www.php.net/manual/en/function.count.php)в конце функции. Это сделано для того, чтобы я мог правильно отображать количество сообщений с этим атрибутом.
Я собираюсь написать для этого две вспомогательные функции, а затем вернусь к sizeofвызову.
Вот вспомогательная функция для нахождения количества результатов, которые имеют указанный meta_keyи meta_valueкоторый у нас есть для этого типа сообщения. Обратите внимание, что я использую [$wpdb](https://developer.wordpress.org/reference/classes/wpdb/)для прямого вызова базы данных и что я специально использую [prepare](https://developer.wordpress.org/reference%2Fclasses%2Fwpdb%2Fprepare%2F/), чтобы убедиться, что я делаю это безопасно.
function get_headline_results(): array {
global $wpdb;
return $wpdb->get_results(
$wpdb->prepare(
"
SELECT post_id FROM $wpdb->postmeta
WHERE meta_key = %s AND meta_value = %s
",
'article_attribute',
'headline'
),
ARRAY_A
);
}
Обратите внимание, что он возвращает все результаты (а не только число), потому что это значение будет моментально передано в другую функцию.
На этом этапе мы могли бы остановиться и просто посмотреть на содержимое, возвращаемое запросом, но если нас интересует только postтип сообщения, нам нужно будет это учитывать. Вот один из способов сделать это:
function filter_posts_from_pages( array $results ): array {
$post_ids = array();
foreach ($results as $result) {
if ('post' === get_post_type( $result['post_type'])) {
$post_ids[] = $result['post_id'];
}
}
return $post_ids;
}
При этом мы можем вернуть это значение обратно в countфункцию выше.
Окончательная версия блока, которую мы начали выше, должна выглядеть примерно так:
array_push(
$views,
sprintf(
'<a href="%1$s" %2$s>%3$s <span class="count">(%4$s)</span></a>',
add_query_arg(
array(
'post_type' => 'post',
'post_status' => 'all',
'meta_value' => 'headlines',
),
'edit.php'
),
$attributes,
__( 'Headlines' ),
count(
filter_posts_from_pages( get_headline_results()) )) );
Это означает, что полная версия функции добавления нового заголовка выглядит примерно так:
add_action(
'views_edit-post',
function (array $views) {
$attributes = 'class=""';
if (filter_input( INPUT_GET, 'meta_value') === 'headline') {
$attributes = 'class="current aria-current="page"';
}
array_push(
$views,
sprintf(
'<a href="%1$s" %2$s>%3$s <span class="count">(%4$s)</span></a>',
add_query_arg(
array(
'post_type' => 'post',
'post_status' => 'all',
'meta_value' => 'headline',
),
'edit.php'
),
$attributes,
__( 'Headlines' ),
count(
filter_posts_from_pages( get_headline_results()) )) );
return $views;
}
);
И, как упоминалось с самого начала, этот плагин не имеет пространства имен и не организован так, как я обычно пишу код. Вместо этого он призван продемонстрировать способ быстрого достижения чего-то — своего рода прототип.
Поэтому, если вам интересно увидеть что-то подобное в действии, вы можете проверить репозиторий на GitHub. Обратите внимание, что на данный момент это ветка разработки . Не забудьте просмотреть, [README](https://github.com/tommcfarlin/custom-metadata-filter/blob/develop/README.md)так как он даст инструкции о том, как добавить данные в базу данных для сообщений, чтобы привязка заголовков действительно работала, а не безоговорочно показывала нулевое значение.