programing

워드프레스에서 분류법 또는 사용자 정의 필드를 동시에 조회하려면 어떻게 해야 합니까?

testmans 2023. 11. 6. 21:41
반응형

워드프레스에서 분류법 또는 사용자 정의 필드를 동시에 조회하려면 어떻게 해야 합니까?

저는 카테고리 또는 사용자 정의 필드로 일치할 수 있는 결과를 반환하는 워드프레스 게시물을 조회해야 합니다.아래 코드를 사용하면 결과가 카테고리 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_replaceSQL 쿼리에 적용할 수 있습니다.

이건 너무 제한적일 수도 있지만 도전입니다 ;-)

따라서 다음을 시도해 볼 수 있습니다.

$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

반응형