我创建了一个自定义帖子类型,并在其中附加了一些自定义字段。现在,我希望作者可以在自定义帖子列表屏幕(在管理后端)中执行搜索,也可以在meta字段中执行搜索,而不仅像往常一样查找标题和内容。

在哪里可以挂接以及必须使用什么代码?

示例图像


Stefano

评论

一个老问题,但是..i建议隐藏屏幕快照中的电子邮件地址和名称...

#1 楼

我解决了通过在postmeta表上添加联接并更改where子句来过滤查询的问题。
有关过滤WHERE子句的提示(通常需要正则表达式搜索和替换)在法典上:

add_filter( 'posts_join', 'segnalazioni_search_join' );
function segnalazioni_search_join ( $join ) {
    global $pagenow, $wpdb;

    // I want the filter only when performing a search on edit page of Custom Post Type named "segnalazioni".
    if ( is_admin() && 'edit.php' === $pagenow && 'segnalazioni' === $_GET['post_type'] && ! empty( $_GET['s'] ) ) {    
        $join .= 'LEFT JOIN ' . $wpdb->postmeta . ' ON ' . $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }
    return $join;
}

add_filter( 'posts_where', 'segnalazioni_search_where' );
function segnalazioni_search_where( $where ) {
    global $pagenow, $wpdb;

    // I want the filter only when performing a search on edit page of Custom Post Type named "segnalazioni".
    if ( is_admin() && 'edit.php' === $pagenow && 'segnalazioni' === $_GET['post_type'] && ! empty( $_GET['s'] ) ) {
        $where = preg_replace(
            "/\(\s*" . $wpdb->posts . ".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",
            "(" . $wpdb->posts . ".post_title LIKE ) OR (" . $wpdb->postmeta . ".meta_value LIKE )", $where );
    }
    return $where;
}


评论


哇!正是我一直在寻找的东西。但是,我认为我可能发现了一个错误,当搜索帖子标题时,我得到一个匹配项,然后在结果中重复5次!!! imgur.com/eE52gIA

– jnthnclrk
13年8月22日在14:58

这是另一个印有SQL的代码:tinypic.com/view.php?pic=124tqb6&s=5无法弄清楚为什么我得到5个项目!

– jnthnclrk
13年8月22日在20:19

发表了一个有关解决伪造错误的单独问题:wordpress.stackexchange.com/questions/111185/…

– jnthnclrk
13年8月24日在11:47

这和下面的帖子对我很有用。现在,找到一种包括搜索帖子作者并显示他们完成的帖子的方法。

– Shawn Rebelo
18年7月31日在18:27

@Stefano,搜索结果正常。有一个问题,默认字段“帖子标题”,搜索记录重复了很多次,并且在管理员端。参见:imgur.com/a/W4wmXhO

–穆罕默德·比拉勒(Muhammad Bilal)
18-10-23在9:16



#2 楼

Stefano的答案很好,但是缺少一个明显的子句:

function segnalazioni_search_distinct( $where ){
    global $pagenow, $wpdb;

    if ( is_admin() && $pagenow=='edit.php' && $_GET['post_type']=='segnalazioni' && $_GET['s'] != '') {
    return "DISTINCT";

    }
    return $where;
}
add_filter( 'posts_distinct', 'segnalazioni_search_distinct' );


添加上面的代码对其进行更新,它将不会重复。

#3 楼

这将起作用,

function custom_search_query( $query ) {
    $custom_fields = array(
        // put all the meta fields you want to search for here
        "rg_first_name",
        "rg_1job_designation"
    );
    $searchterm = $query->query_vars['s'];

    // we have to remove the "s" parameter from the query, because it will prevent the posts from being found
    $query->query_vars['s'] = "";

    if ($searchterm != "") {
        $meta_query = array('relation' => 'OR');
        foreach($custom_fields as $cf) {
            array_push($meta_query, array(
                'key' => $cf,
                'value' => $searchterm,
                'compare' => 'LIKE'
            ));
        }
        $query->set("meta_query", $meta_query);
    };
}
add_filter( "pre_get_posts", "custom_search_query");


评论


请正确地缩进您的代码,并说明为什么这样做以及如何工作。

–tfrommen
2014年1月31日上午11:28

尽管我首先提出了建议,但是我意识到,不幸的是,这将对每个搜索都起作用,因为它可能会破坏前端搜索。

– Maciej Paprocki
18年6月13日在13:01

添加检查是否($ query-> query ['post_type']!='your_custom_post_type'){返回; } top函数顶部将阻止它在其他搜索上运行。请注意,此答案中的技术不再搜索post_title并将其添加回去并不容易。

– jwinn
18年11月30日在18:21

另一个问题-指标“ ”的搜索结果调用get_search_query(),该调用进一步调用get_query_var('s')。由于“ s”设置为空字符串,因此“”的搜索结果在引号之间始终具有空值。此解决方案是否有解决此问题的调整?

– jschrab
19年1月29日在21:01



#4 楼

答案1:
将此代码添加到功能文件中,并更改并添加更多用在自定义帖子类型中的列名

function extend_admin_search( $query ) {

    // use your post type
    $post_type = 'document';
    // Use your Custom fields/column name to search for
    $custom_fields = array(
        "_file_name",
    );

    if( ! is_admin() )
        return;

    if ( $query->query['post_type'] != $post_type )
        return;

    $search_term = $query->query_vars['s'];

    // Set to empty, otherwise it won't find anything
    $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 );
    };
}

add_action( 'pre_get_posts', 'extend_admin_search' );


答案2 :推荐
在功能文件中使用此代码,无需进行任何更改

function cf_search_join( $join ) {
    global $wpdb;

    if ( is_search() ) {    
        $join .=' LEFT JOIN '.$wpdb->postmeta. ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';
    }

    return $join;
}
add_filter('posts_join', 'cf_search_join' );
function cf_search_where( $where ) {
    global $pagenow, $wpdb;

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

    return $where;
}
add_filter( 'posts_where', 'cf_search_where' );

function cf_search_distinct( $where ) {
    global $wpdb;

    if ( is_search() ) {
        return "DISTINCT";
    }

    return $where;
}
add_filter( 'posts_distinct', 'cf_search_distinct' );


#5 楼

这不是搜索,而是通过不同的值进行一些“选择”。

在文件功能-iworks-posts-filter.zip中,您有一个示例,如何通过一些meta_key为常规帖子添加过滤器。我认为转换起来很容易。

评论


谢谢您的帮助...我现在就来看您的随身物品。我会让你知道我调查的结果;-) Stefano

–斯特凡诺
2011-3-14在8:09



Marcin我认为您正在使用“按日期”等过滤器,但是我需要插入上方的“免费搜索”字段。无论如何,我刚刚发布了我的解决方案,也许它会有所帮助,谢谢!

–斯特凡诺
2011-3-18在9:03



#6 楼

几个答案中的代码版本修改了pre_get_posts中搜索的WP_Query的meta_query参数,不再搜索post_title。不幸的是,添加该功能可以搜索WP_Query中的帖子标题或OR元值,而无需修改SQL,这是很费力的,因为这个问题涉及:在搜索查询('s')中使用元查询('meta_query')

我已经结合了这里的一些技术来获得可以避免preg_replaces和过多的SQL修改的工作版本(我希望可以完全避免)。唯一的缺点是搜索后,页面顶部的字幕文本显示为“的搜索结果”。我只是使用CSS将其隐藏为插件的自定义帖子类型。

/**
 * Extend custom post type search to also search meta fields
 * @param  WP_Query $query
 */
function extend_cpt_admin_search( $query ) {
  // Make sure we're in the admin area and that this is our custom post type
  if ( !is_admin() || $query->query['post_type'] != 'your_custom_post_type' ){
    return;
  }

  // Put all the meta fields you want to search for here
  $custom_fields = array(
    "your_custom_meta_field",
    "your_custom_meta_field2",
    "your_custom_meta_field3"
  );
  // The string submitted via the search form
  $searchterm = $query->query_vars['s'];

  // Set to empty, otherwise no results will be returned.
  // The one downside is that the displayed search text is empty at the top of the page.
  $query->query_vars['s'] = '';

  if ($searchterm != ""){
    // Add additional meta_query parameter to the WP_Query object.
    // Reference: https://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters
    $meta_query = array();
    foreach($custom_fields as $cf) {
      array_push($meta_query, array(
        'key' => $cf,
        'value' => $searchterm,
        'compare' => 'LIKE'
      ));
    }
    // Use an 'OR' comparison for each additional custom meta field.
    if (count($meta_query) > 1){
      $meta_query['relation'] = 'OR';
    }
    // Set the meta_query parameter
    $query->set('meta_query', $meta_query);


    // To allow the search to also return "OR" results on the post_title
    $query->set('_meta_or_title', $searchterm);
  }
}
add_action('pre_get_posts', 'extend_cpt_admin_search');



/**
 * WP_Query parameter _meta_or_title to allow searching post_title when also
 * checking searching custom meta values
 * https://wordpress.stackexchange.com/questions/78649/using-meta-query-meta-query-with-a-search-query-s
 * https://wordpress.stackexchange.com/a/178492
 * This looks a little scary, but basically it's modifying the WHERE clause in the 
 * SQL to say "[like the post_title] OR [the existing WHERE clause]"
 * @param  WP_Query $q
 */
function meta_or_title_search( $q ){
  if( $title = $q->get( '_meta_or_title' ) ){
    add_filter( 'get_meta_sql', function( $sql ) use ( $title ){
      global $wpdb;

      // Only run once:
      static $nr = 0;
      if( 0 != $nr++ ) return $sql;

      // Modified WHERE
      $sql['where'] = sprintf(
          " AND ( (%s) OR (%s) ) ",
          $wpdb->prepare( "{$wpdb->posts}.post_title LIKE '%%%s%%'", $title),
          mb_substr( $sql['where'], 5, mb_strlen( $sql['where'] ) )
      );

      return $sql;
    });
  }
}
add_action('pre_get_posts', 'meta_or_title_search');


#7 楼

使用此代码,您可以在WordPress管理控制台中的帖子列表中搜索自定义帖子元值以及标题和其他默认字段。

请在functions.php文件中添加以下代码:

if (!function_exists('extend_admin_search')) {
    add_action('admin_init', 'extend_admin_search');

    /**
     * hook the posts search if we're on the admin page for our type
     */
    function extend_admin_search() {
        global $typenow;

        if ($typenow === 'your_custom_post_type') {
            add_filter('posts_search', 'posts_search_custom_post_type', 10, 2);
        }
    }

    /**
     * add query condition for custom meta
     * @param string $search the search string so far
     * @param WP_Query $query
     * @return string
     */
    function posts_search_custom_post_type($search, $query) {
        global $wpdb;

        if ($query->is_main_query() && !empty($query->query['s'])) {
            $sql    = "
            or exists (
                select * from {$wpdb->postmeta} where post_id={$wpdb->posts}.ID
                and meta_key in ('custom_field1','custom_field2')
                and meta_value like %s
            )
        ";
            $like   = '%' . $wpdb->esc_like($query->query['s']) . '%';
            $search = preg_replace("#\({$wpdb->posts}.post_title LIKE [^)]+\)\K#",
                $wpdb->prepare($sql, $like), $search);
        }

        return $search;
    }
}


评论


请不要将您的答案复制到每个匹配的问题上。获得足够的声誉后,您就可以在任何帖子中发表评论,并提供答案的链接。

– nmr
20年1月21日,11:13

我试图帮助遇到类似问题的所有人,并努力寻找正确的答案。

–塞巴·塞巴迪(Sebed Abbas Seyedi)
20年1月22日在11:24