Поиск администратора WordPress: расширение результатов

Опубликовано: 2021-01-20

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

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

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

Расширьте поисковый запрос на экране администратора

В нашем рабочем примере с настраиваемыми полями мы создали настраиваемое поле под названием «источник» в одном из наших сообщений и вставили значение URL.

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

Чтобы изменить это, нам нужно расширить исходный хук, который WordPress предоставляет для функции поиска. Хук, который мы должны расширить, — это pre_get_posts , включенный в файл wp-includes/class-wp-query.php в строке 1779 внутри функции get_posts .

Запрос WordPress

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

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

Чтобы просмотреть запрос до его выполнения, мы добавим печать в хук действия pre_get_posts . Фильтр pre_get_posts срабатывает после создания объекта переменной запроса, но до фактического запуска запроса.

В файл functions.php вашей активной темы вставьте этот фрагмент кода:

 add_action( 'pre_get_posts', 'print_query' ); function print_query( ) { print_r ( $GLOBALS['wp_query']->query ); echo "<hr>"; print_r ( $GLOBALS['wp_query']->query_vars ); echo "<hr>"; }

Теперь, если вы посетите экран администратора сообщений, результаты query и query_var будут напечатаны вверху.

Для более удобного просмотра кода вы можете скопировать и вставить его в бесплатный онлайн-улучшитель PHP.

Массив $GLOBALS['wp_query']->query (first out) будет выглядеть следующим образом:

 Array ( [order] => [orderby] => [post_type] => post [posts_per_page] => 20 [post_status] => [perm] => )

Например, в случае поиска на экране администратора сообщений вывод массива изменится, включая строку поиска. Если мы ищем, например, «wordpress.org», это будет выглядеть так:

 Array ( [m] => 0 [cat] => 0 [s] => wordpress.org [paged] => 1 [order] => [orderby] => [post_type] => post [posts_per_page] => 20 [post_status] => [perm] => )

Соберите код

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

 add_action( 'pre_get_posts', 'extend_admin_search' ); function extend_admin_search( $query ) { $post_type = 'post'; $custom_fields = array("source",); if( ! is_admin() ) return; if ( $query->query['post_type'] != $post_type ) return; $search_term = $query->query_vars['s']; $query->query_vars['s'] = ''; if ( $search_term != '' ) { $meta_query = array( 'relation' => 'OR' ); foreach( $custom_fields as $custom_field ) { array_push( $meta_query, array( 'key' => $custom_field, 'value' => $search_term, 'compare' => 'LIKE' )); } $query->set( 'meta_query', $meta_query ); }; }

Следующий шаг — изменить переменные $post_type и $custom_fields на значения, соответствующие вашим требованиям. Давайте посмотрим, что мы сделали в коде.

  • $post_type = 'post'; – Здесь мы определяем тип поста, который мы хотим искать.
  • $custom_fields = array("source",); – Здесь мы определяем настраиваемые поля, которые мы хотим искать.

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

  • if ( ! is_admin() ) return; Условие гарантирует, что если мы не находимся в области администратора, ни один из наших кодов не будет выполняться.
  • Функция if ( $query->query['post_type'] != $post_type ) проверяет, работаем ли мы с типом записи, который мы определили в переменной $post_type . В нашем случае post .
  • $search_term = $query->query_vars['s']; здесь мы сохраняем строку поиска в переменной, а затем снова устанавливаем ее пустой $query->query_vars['s'] = ''; иначе ничего не найдет.

Теперь, с этими обновлениями, если вы обновите последний поиск, вы получите правильные результаты. В нашем случае мы видим в результатах сообщение «Публикация 1», которое включает в себя запись пользовательского поля «источник»: «https://dev. wordpress.org/reference/functions/add_post_meta/ '.

улучшить поиск в админке wordpress

Расширение поискового запроса в поиске спереди

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

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

В идеале мы хотим, чтобы пользователи могли искать эти поля. В этом примере у нас есть пользовательское поле «источник» в одном из наших сообщений, которое в настоящее время содержит URL-адрес «https://dev.wordpress.org/reference/functions/add_post_meta/». Если пользователь ищет «wordpress.org», этот пост должен появиться в результатах. Давайте узнаем, как это сделать.

Требуемый код

Снова зайдите в свой файл functions.php и скопируйте код, который вы вставили ранее. Теперь вставьте это прямо под этим кодом (чтобы у вас было две копии этого кода в functions.php ). Теперь измените имя функции во втором фрагменте кода на что-то вроде extend_front_search . Это должно выглядеть так:

 add_action( 'pre_get_posts', 'extend_admin_search' ); function extend_admin_search( $query ) { $post_type = 'post'; $custom_fields = array("source",); if( ! is_admin() ) return; if ( $query->query['post_type'] != $post_type ) return; $search_term = $query->query_vars['s']; $query->query_vars['s'] = ''; if ( $search_term != '' ) { $meta_query = array( 'relation' => 'OR' ); foreach( $custom_fields as $custom_field ) { array_push( $meta_query, array( 'key' => $custom_field, 'value' => $search_term, 'compare' => 'LIKE' )); } $query->set( 'meta_query', $meta_query ); }; }

Затем нам нужно удалить if ( $query->query['post_type'] != $post_type ) return; условие.

 add_action( 'pre_get_posts', 'extend_front_search' ); function extend_front_search( $query ) { $post_type = 'post'; $custom_fields = array("source",); if( is_admin() ) return; $search_term = $query->query_vars['s']; $query->query_vars['s'] = ''; if ( $search_term != '' ) { $meta_query = array( 'relation' => 'OR' ); foreach( $custom_fields as $custom_field ) { array_push( $meta_query, array( 'key' => $custom_field, 'value' => $search_term, 'compare' => 'LIKE' )); } $query->set( 'meta_query', $meta_query ); }; }

Нам просто нужно поддерживать условие if( is_admin() ) return; чтобы убедиться, что код будет применяться только во внешнем интерфейсе, и мы готовы к работе.

Альтернативная стратегия

Еще один способ расширить поиск WordPress, включив в него настраиваемые поля, — изменить SQL-запрос.

Класс WP_Query поможет вам в этом, разбив его на части, как описано в строке 2897 файла wp-includes/class-wp-query.php .

 $clauses = (array) apply_filters_ref_array( 'posts_clauses_request', array( compact( $pieces ), &$this ) ); $where = isset( $clauses['where'] ) ? $clauses['where'] : ''; $groupby = isset( $clauses['groupby'] ) ? $clauses['groupby'] : ''; $join = isset( $clauses['join'] ) ? $clauses['join'] : ''; $orderby = isset( $clauses['orderby'] ) ? $clauses['orderby'] : ''; $distinct = isset( $clauses['distinct'] ) ? $clauses['distinct'] : ''; $fields = isset( $clauses['fields'] ) ? $clauses['fields'] : ''; $limits = isset( $clauses['limits'] ) ? $clauses['limits'] : '';

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

 function join_meta_table( $join ) { global $wpdb; if ( is_search() ) { $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '..post_id '; } return $join; } add_filter('posts_join', 'join_meta_table' );

Конечно, мы использовали хук posts_join , так как он фильтрует предложение JOIN запроса.

Далее мы воспользуемся хуком posts_where , чтобы изменить часть запроса WHERE в соответствии с нашими потребностями.

 function modify_where_clause( $where ) { global $pagenow, $wpdb; if ( is_search() ) { $where = preg_replace( "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/", "(".$wpdb->posts.".post_title LIKE $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $where ); } return $where; } add_filter( 'posts_where', 'modify_where_clause' );

И последнее, но не менее важное: нам нужно предотвратить дублирование. Для этого мы используем хук posts_distinct , который фильтрует предложение DISTINCT запроса.

 function prevent_duplicates( $where ) { global $wpdb; if ( is_search() ) { return "DISTINCT"; } return $where; } add_filter( 'posts_distinct', 'prevent_duplicates' );

Теперь давайте посмотрим, что произойдет во внешнем интерфейсе, если мы найдем строку «wordpress.org».

поиск wordpress в интерфейсе

Как и ожидалось, на этот раз результаты правильные. Поиск WordPress нашел «сообщение 1» в результате, так как оно содержит поле «источник» со значением «https://dev. wordpress.org /ссылка/функции/add_post_meta/

Пользовательские типы записей в результатах поиска WordPress

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

Давайте представим, что мы создали пользовательский тип сообщений с именем «книги» и хотим, чтобы этот тип сообщений отображался в результатах поиска. На этот раз нам не нужно заново создавать SQL-запрос, а только переопределить типы сообщений в pre_get_posts , как показано ниже. Код нужно еще раз поместить в файл functions.php .

 function tg_include_custom_post_types_in_search_results( $query ) { if ( $query->is_main_query() && $query->is_search() && ! is_admin() ) { $query->set( 'post_type', array( 'post', 'books' ) ); } } add_action( 'pre_get_posts', 'tg_include_custom_post_types_in_search_results' );

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

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

Вывод

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