답변:
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 $1) OR (" . $wpdb->postmeta . ".meta_value LIKE $1)", $where );
}
return $where;
}
스테파노의 대답은 훌륭하지만 별개의 절이 없습니다.
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' );
위의 코드를 업데이트하면 중복없이 작동합니다.
이 작동합니다
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");
if ( $query->query['post_type'] != 'your_custom_post_type' ){ return; }
함수 상단에 체크 표시를 추가하면 다른 검색에서이 기능이 실행되지 않습니다. 이 답변의 기술은 더 이상 post_title을 검색하지 않으며 다시 추가하는 것이 쉽지 않습니다.
get_search_query()
더 통화 get_query_var( 's' )
. "s"가 빈 문자열로 설정되어 있으므로 ""에 대한 검색 결과 는 항상 따옴표 사이에 빈 값을 갖습니다. 이 문제를 해결하는이 솔루션에 대한 조정이 있습니까?
답변 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 $1) OR (".$wpdb->postmeta.".meta_value LIKE $1)", $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' );
검색이 아니라 고유 한 값으로 "선택"됩니다.
functions-iworks-posts-filter.zip 파일 에 일부 meta_key로 일반 게시물에 대한 필터를 추가하는 방법에 대한 예제가 있습니다. 변환하기 쉽다고 생각합니다.
pre_get_posts에서 검색 WP_Query의 meta_query 매개 변수를 수정하는 몇 가지 답변의 코드 버전이 더 이상 post_title을 검색하지 않았습니다. 검색 할 수있는 기능 중 하나 게시물 제목을 추가, 또는 메타 값에이 질문에 정성 들여으로, 불행하게도 SQL을 수정하지 않고 WP_Query에서 직접 수행 할 수 없습니다 ( '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');