워드프레스에서 분류법 또는 사용자 정의 필드를 동시에 조회하려면 어떻게 해야 합니까?
저는 카테고리 또는 사용자 정의 필드로 일치할 수 있는 결과를 반환하는 워드프레스 게시물을 조회해야 합니다.아래 코드를 사용하면 결과가 카테고리 AND 사용자 정의 필드로 일치하는 경우에만 결과를 반환합니다.두 쿼리 중 하나로 일치할 수 있는 일치 항목을 찾아야 해서 "OR" 결과가 나오지만 작동하지 않는 것 같습니다.
누가 도와줄 수 있습니까?
$args = array(
'post_type' => 'post',
'tax_query' => array(
'relation' => 'OR',
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => array( 'arts','food' ),
'operator' => 'IN'
)
),
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'birth_city',
'value' => 'London',
'compare' => 'IN',
),
)
);
버전 0.2
이전 답변과 혼동을 피하기 위해 새로운 답변으로 추가하는 것을 양해해 주시기 바랍니다.
여기서는 워드프레스 기능을 사용합니다.get_meta_sql()
그리고.get_tax_sql()
, 수정하다, 수정.WHERE
생성된 SQL의 일부WP_Query()
:
/**
* Class WPSE_OR_Query
*
* Add a support for (tax_query OR meta_query)
*
* @version 0.2
* @link http://stackoverflow.com/a/22633399/2078474
*
*/
class WPSE_OR_Query extends WP_Query
{
protected $meta_or_tax = FALSE;
protected $tax_args = NULL;
protected $meta_args = NULL;
public function __construct( $args = array() )
{
add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 999 );
add_filter( 'posts_where', array( $this, 'posts_where' ), 999 );
parent::__construct( $args );
}
public function pre_get_posts( $qry )
{
remove_action( current_filter(), array( $this, __FUNCTION__ ) );
// Get query vars
$this->meta_or_tax = ( isset( $qry->query_vars['meta_or_tax'] ) ) ? $qry->query_vars['meta_or_tax'] : FALSE;
if( $this->meta_or_tax )
{
$this->tax_args = ( isset( $qry->query_vars['tax_query'] ) ) ? $qry->query_vars['tax_query'] : NULL;
$this->meta_args = ( isset( $qry->query_vars['meta_query'] ) ) ? $qry->query_vars['meta_query'] : NULL;
}
}
public function posts_where( $where )
{
global $wpdb;
$field = 'ID';
remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
// Construct the "tax OR meta" query
if( $this->meta_or_tax && is_array( $this->tax_args ) && is_array( $this->meta_args ) )
{
// Tax query
$sql_tax = get_tax_sql( $this->tax_args, $wpdb->posts, $field );
// Meta query
$sql_meta = get_meta_sql( $this->meta_args, 'post', $wpdb->posts, $field );
// Modify the 'where' part
if( isset( $sql_meta['where'] ) && isset( $sql_tax['where'] ) )
{
$where = str_replace( array( $sql_meta['where'], $sql_tax['where'] ) , '', $where );
$where .= sprintf( ' AND ( %s OR %s ) ', substr( trim( $sql_meta['where'] ), 4 ), substr( trim( $sql_tax['where'] ), 4 ) );
}
}
return $where;
}
}
이것이 당신의 문제를 해결하기 위한 첫 번째 시도입니다.저는 다음과 같은 제한 내에서 일을 했습니다.
- SQL 쿼리를 직접 작성하지 않음
- 연장하다, 연장.
WP_Query
- 사용하다
WP_Tax_Query
그리고.WP_Meta_Query
- 쓰지 마
preg_replace
/str_replace
SQL 쿼리에 적용할 수 있습니다.
이건 너무 제한적일 수도 있지만 도전입니다 ;-)
따라서 다음을 시도해 볼 수 있습니다.
$args = array(
'post_type' => 'post',
'meta_or_tax' => TRUE,
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'slug',
'terms' => array( 'birds','falcons' ),
'operator' => 'IN'
)
),
'meta_query' => array(
array(
'key' => 'birth_city',
'value' => 'London',
'compare' => 'IN',
),
)
);
$q = new WPSE_OR_Query( $args );
여기서 새로운 매개변수를 소개합니다.meta_or_tax
:
`meta_or_tax` => FALSE
당신에게 평범한 것을 줄 것입니다.WP_Query
행동과
`meta_or_tax` => TRUE
를 얻을 수 있게 해 줄 것입니다.OR
디폴트 대신에AND
세금 쿼리와 메타 쿼리 사이에.
더뉴WPSE_OR_Query
클래스는 다음과 같이 정의됩니다.
/**
* Class WPSE_OR_Query
*
* Add a support for (tax_query OR meta_query)
*
* @link http://stackoverflow.com/a/22616337/2078474
*
*/
class WPSE_OR_Query extends WP_Query
{
protected $meta_or_tax = FALSE;
protected $tax_args = NULL;
protected $meta_args = NULL;
public function __construct( $args = array() )
{
add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 10 );
add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), 10 );
parent::__construct( $args );
}
public function pre_get_posts( $qry )
{
remove_action( current_filter(), array( $this, __FUNCTION__ ) );
// Get query vars
$this->meta_or_tax = ( isset( $qry->query_vars['meta_or_tax'] ) ) ? $qry->query_vars['meta_or_tax'] : FALSE;
if( $this->meta_or_tax )
{
$this->tax_args = ( isset( $qry->query_vars['tax_query'] ) ) ? $qry->query_vars['tax_query'] : NULL;
$this->meta_args = ( isset( $qry->query_vars['meta_query'] ) ) ? $qry->query_vars['meta_query'] : NULL;
// Unset meta and tax query
unset( $qry->query_vars['meta_query'] );
unset( $qry->query_vars['tax_query'] );
}
}
public function posts_clauses( $clauses )
{
global $wpdb;
$field = 'ID';
remove_filter( current_filter(), array( $this, __FUNCTION__ ) );
// Reconstruct the "tax OR meta" query
if( $this->meta_or_tax && is_array( $this->tax_args ) && is_array( $this->meta_args ) )
{
// Tax query
$tax_query = new WP_Tax_Query( $this->tax_args );
$sql_tax = $tax_query->get_sql( $wpdb->posts, $field );
// Meta query
$meta_query = new WP_Meta_Query( $this->meta_args );
$sql_meta = $meta_query->get_sql( 'post', $wpdb->posts, $field );
// Where part
if( isset( $sql_meta['where'] ) && isset( $sql_tax['where'] ) )
{
$t = substr( trim( $sql_tax['where'] ), 4 );
$m = substr( trim( $sql_meta['where'] ), 4 );
$clauses['where'] .= sprintf( ' AND ( %s OR %s ) ', $t, $m );
}
// Join/Groupby part
if( isset( $sql_meta['join'] ) && isset( $sql_tax['join'] ) )
{
$clauses['join'] .= sprintf( ' %s %s ', $sql_meta['join'], $sql_tax['join'] );
$clauses['groupby'] .= sprintf( ' %s.%s ', $wpdb->posts, $field );
}
}
return $clauses;
}
}
다음은 일반 SQL의 예입니다.
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (15,70) )
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
AND ( (wp_postmeta.meta_key = 'birth_city' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('London')) )
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC LIMIT 0, 10
수정된 버전의 SQL:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id)
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')
AND ( ( (wp_postmeta.meta_key = 'birth_city' AND CAST(wp_postmeta.meta_value AS CHAR) IN ('London')) ) OR ( wp_term_relationships.term_taxonomy_id IN (15,70) ) )
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC LIMIT 0, 10
이것은 물론 훨씬 더 개선될 수 있으며 여러분의 필요에 따라 확장할 수 있기를 바랍니다.
도움이 되길 바랍니다.
WP_Query로 수행하는 방법을 찾지 못했지만, 도움이 된다면 쿼리를 수동으로 작성하는 방법이 있습니다. 쿼리가 보기 흉하게 보이지만 쿼리만 사용할 수 있다면 다음과 같은 목적을 달성할 수 있습니다.
$results = $wpdb->get_results( $wpdb->prepare( "
SELECT * FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON($wpdb->posts.ID = $wpdb->postmeta.post_id)
LEFT JOIN $wpdb->term_relationships ON($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
LEFT JOIN $wpdb->terms ON($wpdb->term_taxonomy.term_id = $wpdb->terms.term_id)
WHERE $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->term_taxonomy.taxonomy = 'category'
AND $wpdb->terms.name IN ( %s, %s )
OR ( $wpdb->postmeta.meta_key = %s
AND $wpdb->postmeta.meta_value = %s )
ORDER BY $wpdb->posts.post_date DESC
", 'arts', 'food', 'birth_city', 'London' ), OBJECT_K );
언급URL : https://stackoverflow.com/questions/22611782/how-do-i-query-taxonomy-or-custom-field-in-wordpress-at-the-same-time
'programing' 카테고리의 다른 글
스크롤할 때 메뉴 바를 상단에 고정한 채로 둡니다. (0) | 2023.11.06 |
---|---|
서명되지 않은 int 0xFFFFFFFF가 int -1과 같은 이유는 무엇입니까? (0) | 2023.11.06 |
jQuery에서 Grep vs 필터? (0) | 2023.11.06 |
mysql에서 구별되는 2개의 열 조합 선택 (0) | 2023.11.06 |
저장 프로시저의 변수에 선택 할당 (0) | 2023.11.06 |