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

11

Я играл с фрагментами кода, которые добавляют метаданные к поискам администратора.

Лучший фрагмент, который я нашел, был написан Стефано по этому вопросу .

Тем не менее, он, похоже, имеет 1, досадную ошибку при поиске неметайных терминов.

Вот некоторые примеры из моей локальной установки dev. Я напечатал 2 запроса MySQL на экран.

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

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

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

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

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

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

Захват, показывающий статус поста, тип поста и пост предков дупов

! Захват, показывающий статус поста, тип поста и пост предков дупов

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

/*
 * Search custom fields from admin keyword searches
 */

function rel_search_join( $join ) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type'] == 'listings' && $_GET['s'] != '') {    
        $join .= 'LEFT JOIN ' . $wpdb->postmeta . ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    echo '<br><strong>JOIN</strong>: ';
    print_r ( $join );
    echo '<br>';
    return $join;
}
add_filter('posts_join', 'rel_search_join' );

function rel_search_where( $where ) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type']=='listings' && $_GET['s'] != '' ) {
        $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 );
        $where = str_replace( "OR wp_posts.post_status = 'pending'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'private'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'draft'", "", $where );
        $where = str_replace( "OR wp_posts.post_status = 'future'", "", $where );
    }
    echo '<br><strong>WHERE</strong>: ';
    print_r ( $where );
    echo '<br>';
    return $where;
}
add_filter( 'posts_where', 'rel_search_where' );  
jnthnclrk
источник
Может быть, в нем тоже перечислены ревизии?
Passatgt
Я думал, что смотрю только на опубликованные, потому что я удалил ожидающие, частные, черновик и будущее. Не заметил тип ревизии.
jnthnclrk
Хммм, похоже, что статус «редакции» отсутствует: codex.wordpress.org/Post_Status
jnthnclrk
попытайтесь напечатать тип сообщения или идентификатор сообщения в одном из столбцов, я думаю, что ревизии являются типами постов, поэтому, если вы видите ревизии, это также есть в результатах. Но я также вижу, что вы отображаете результаты только по типу записей в списках, поэтому я не прав. Но стоит попробовать :)
passatgt
Добавлен новый захват со статусами постов, типами постов и постами предков.
jnthnclrk

Ответы:

11

GROUP BYМожно сгруппировать заявление ваши сообщения после того , как JOIN. Для Wordpress вы можете использовать posts_groupbyфильтр.

add_filter( 'posts_groupby', 'my_post_limits' );
function my_post_limits($groupby) {
    global $pagenow, $wpdb;
    if ( is_admin() && $pagenow == 'edit.php' && $_GET['post_type']=='listings' && $_GET['s'] != '' ) {
        $groupby = "$wpdb->posts.ID";
    }
    return $groupby;
}
epilektric
источник
4

Спасибо за вашу работу над этим, ребята. Этот код помог мне пройти большую часть пути, но в WP 3.8 я получил ошибку неуникальной таблицы / псевдонима SQL, поэтому внес некоторые изменения. Чтобы это работало в моей настройке, я должен был установить псевдоним $ wpdb-> postmeta, который использовался в операторе JOIN. Я также проверяю только один раз, чтобы увидеть, следует ли использовать крючки, чтобы они не срабатывали каждый раз. Надеюсь, это поможет кому-то!

global $postmeta_alias, $is_specials_search;
$cpt_name = 'special';
$postmeta_alias = 'pdpm'; // Change this to whatever your custom post type is
$is_specials_search = is_admin() && $pagenow=='edit.php' && isset( $_GET['post_type'] ) && $_GET['post_type']==$cpt_name && isset( $_GET['s'] );

// Extend search to include 'description' field
if ( $is_specials_search ) {
  add_filter( 'posts_join',      'pd_description_search_join' );
  add_filter( 'posts_where',     'pd_description_search_where' );
  add_filter( 'posts_groupby',   'pd_search_dupe_fix' );
}

function pd_description_search_join ($join){
  global $pagenow, $wpdb, $postmeta_alias, $is_specials_search;

  if ( $is_specials_search )  
    $join .='LEFT JOIN '.$wpdb->postmeta. ' as ' . $postmeta_alias . ' ON '. $wpdb->posts . '.ID = ' . $postmeta_alias . '.post_id ';

  return $join;
} // END search_join

function pd_description_search_where( $where ){
  global $pagenow, $wpdb, $postmeta_alias, $is_specials_search;

  if ( $is_specials_search )
    $where = preg_replace(
     "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
     "(".$wpdb->posts.".post_title LIKE $1) OR (".$postmeta_alias.".meta_value LIKE $1)", $where );

  return $where;
} // END search_where

function pd_search_dupe_fix($groupby) {
    global $pagenow, $wpdb, $is_specials_search;

    if ( $is_specials_search )
      $groupby = "$wpdb->posts.ID";

    return $groupby;
} // END pd_search_dupe_fix
souverian
источник