Pre Get Posts 또는 WP_Query를 사용해야합니까


29

다음을 통해 taxonomy.php 템플릿에서 호출하는 다음 쿼리가 있습니다. query_brands_geo('dealers', 'publish', '1', $taxtype, $geo, $brands);

이 기능은 완벽하게 작동합니다. 그러나 쿼리 게시물의 코덱을 읽은 후 기본 쿼리를 변경하는 기본 방법으로 pre_get_posts를 언급했습니다. pre_get_posts가 아래 wp_query 함수보다 더 효율적입니까?

그렇다면 어떻게 pre_get_posts를 구성하고 변수와 쿼리를 아래에 전달합니까?

function my_custom_query($posttype, $poststatus, $paidvalue, $taxtype, $geo, $brands) {
   global $wp_query; 
   $wp_query = new WP_Query();
   $args = array( 
      'post_type' => $posttype, 
      'post_status' => array($poststatus), 
      'orderby' => 'rand', 
      'posts_per_page' => 30, 
      'meta_query' => array( 
         array( 
            'key' => 'wpcf-paid', 
            'value' => array($paidvalue), 
            'compare' => 'IN', 
            ) 
      ), 
      'tax_query' => array( 
         'relation' => 'AND', 
         array( 
            'taxonomy' => $taxtype, 
            'field' => 'slug', 
            'terms' => $geo 
         ), 
         array( 
            'taxonomy' => 'brands', 
            'field' => 'slug', 
            'terms' => $brands 
         ) 
      ) 
   ); 

   return $wp_query->query($args); 
} 

답변:


14

pre_get_posts동일한 쿼리를 실행하므로 둘 다 같은 시간이 걸립니다. 그러나 pre_get_posts조치 를 사용 하면 하나 이상의 SQL 조회가 저장됩니다. 현재 WordPress는 기본 쿼리를 실행 한 다음 기본 쿼리 결과를 대체하는이 기능으로 쿼리를 실행합니다 (결과, 기본 쿼리는 사용되지 않습니다). 아래는 귀하 $args

function custom_pre_get_posts($query, $posttype='dealers', $poststatus='publish', $paidvalue='1', $taxtype='any_default_value', $geo='any_default_value', $brands='any_default_value') {

    // filter your request here.
    if($query->is_category) {

        $args = array(
            'post_type' => $posttype,
            'post_status' => array($poststatus),
            'orderby' => 'rand',
            'posts_per_page' => 30,
            'meta_query' => array(
                array(
                    'key' => 'wpcf-paid',
                    'value' => array($paidvalue),
                    'compare' => 'IN',
                )
            ),
            'tax_query' => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => $taxtype,
                    'field' => 'slug',
                    'terms' => $geo
                ),
                array(
                    'taxonomy' => 'brands',
                    'field' => 'slug',
                    'terms' => $brands
                )
            )
        );
        $query->query_vars = $args;
    }
}
add_action('pre_get_posts', 'custom_pre_get_posts');

답장을 보내 주셔서 대단히 감사합니다. 매우 도움이됩니다. 간단한 질문입니다. 내 함수 function.php 파일에 함수를 배치했습니다. 내 taxonomy.php에서 custom_pre_get_posts ($ query) 함수를 실행합니다. taxonomy.php에서 변수 $ posttype, $ post_status, $ geo, $ brands, $ taxtype을 설정하고이 변수를 변경하는 두 개의 루프를 실행합니다. taxonomy.php에서 위의 함수에 변수를 전달하는 방법이 있습니까? custom_pre_get_posts ($ query, 'dealers', 'publish', '1', $ taxtype, $ geo, $ brands); custom_pre_get_posts ()에 대해 인수 2에서 7까지 누락되었습니다. add_action으로 인해 가정합니까 ???
user1609391

1
나머지 인수를 허용하도록 custom_pre_get_posts를 변경했다고 가정합니다. 예, add_action으로 인해 오류가 발생했습니다. add_action은 단일 인수 (예 : $ query)로이 함수를 호출하므로 인수 오류가 누락되지 않도록 다른 인수에 기본값을 지정해야합니다. ($ posttype = null, $ poststatus = null ...)과 같이 add_action에 의해 올바르게 호출 될 수 있습니다.
MR

MR 답장을 보내 주셔서 감사합니다. 추가 작업을 읽었으며 우선 순위와 인수 번호를 지정해야합니다. 그래서 추가 작업을 <code> add_action ( 'pre_get_posts', 'custom_pre_get_posts', 10,7); </ code>로 변경했습니다. 그런 다음 taxonomy.php 페이지에서 <code> do_action ( 'pre_get_post', $ query, ' 딜러 ','게시 ','1 ', $ taxtype, $ geo, $ brands); </ code>. 그러나 여전히 같은 오류가 발생합니다. 기본값을 어디에 둘지 잘 모르겠습니다. Google을 시도했지만 참조를 찾을 수 없습니다. 이 문제를 처리하는 방법에 대한 정보를 좀 더 주시겠습니까?
user1609391

답장과 예를 주셔서 감사합니다. 그러나 새로운 워드 프레스 쿼리를 수행해야 할 때 pre_get_posts를 사용하려고했을 수도 있습니다. 검색어를 저장하려고했지만 제 경우에는 불가능할 수 있습니다. 그 이유는 매개 변수에서 설정 한 모든 인수이므로 내 taxonomy.php 파일에서 함수로 전달하고 싶습니다. 따라서 taxonomy.php에서 실행중인 조건에 따라 $ paidvalue =”1”은 1 또는 0 일 수 있습니다. taxonomy.php 파일에서 함수를 호출하지 않아도 페이지가로드되면 바로 위의 pre_get_posts가 실행되는 것 같습니다. 이게 맞습니까?
user1609391

3
이 답변은 현재 작성 되었으므로 의미 가 없습니다. 객체 내부의 모든 값 을 효과적으로 덮어 쓰면$wp_query 완전히 실패합니다. 그 외에도 추가 쿼리를 실행하는 것은 사실아닙니다pre_get_posts ...
kaiser

10

가장 많이 답한 답변으로 늦게 답변하면 쿼리가 중단되고 일부 주요 요점에서는 사실이 아닙니다.

WP_Query과의 필터

첫째, 워드 프레스는 내부적으로 사용 query_posts()(주위에 얇은 래퍼 WP_Query가이 안된다 테마 또는 플러그인을 사용할 수)가 할 WP_Query. 이것은 WP_Query메인 루프 / 쿼리 역할을합니다. 이 쿼리는 실제 SQL 쿼리 문자열이 작성 될 때까지 많은 필터와 작업을 수행합니다. 그 중 하나는입니다 pre_get_posts. 기타는 posts_clauses, posts_where, 등 그 또한 쿼리 문자열 구축 과정을 차단 할 수 있습니다.

코어 내부에서 발생하는 일에 대해 자세히 살펴보기

워드 프레스는 실행 wp()기능 (에서 wp-includes/functions.php호출), $wp->main()( $wp에 정의 된 클래스 WP,의 목적을 wp-includes/class-wp.php). 이것은 WordPress에게 다음을 지시합니다.

  1. 아래에서-more를 사용하여 URL을 쿼리 사양으로 구문 분석하십시오 WP->parse_request().
  2. 이용 조건 태그에 의해 사용되는 모든 IS_ 변수를 설정 $wp_query->parse_query()( $wp_query의 목적 class WP_Query에 정의된다 wp-includes/query.php). 이 함수의 이름에도 불구하고이 경우 WP_Query->parse_query실제로 우리를 위해 어떤 파싱도하지 않습니다.WP->parse_request() .
  3. WP_Query-> get_posts () 함수에서 쿼리 스펙을 MySQL 데이터베이스 쿼리로 변환하고 데이터베이스 쿼리를 실행하여 게시물 목록을 가져 오십시오. WordPress 루프에 사용될 $ wp_query 객체에 게시물을 저장하십시오.

소스 코덱

결론

기본 쿼리를 실제로 수정하려면 다양한 필터를 사용할 수 있습니다. 조건부 검사를 수행 하기 위해 단순히 데이터 $query->set( 'some_key', 'some_value' );변경 하거나 데이터를 검색하는 데 사용하십시오 . 이렇게하면 변경 하면서 두 번째 쿼리를 수행하지 않아도됩니다.$query->get( 'some_key' ); SQL 쿼리 만 하므로 됩니다.

추가 쿼리 를 수행 해야하는 경우WP_Query 객체를 사용하십시오. DB에 다른 쿼리가 추가됩니다.

예제에서 답변이 항상 더 잘 작동함에 따라 여기에 정말 멋진 하나 (Brad Touesnard의 소품)가 있습니다.

class My_Book_Query extends WP_Query
{
    function __construct( $args = array() )
    {
        // Forced/default args
        $args = array_merge( $args, array(
            'posts_per_page' => -1
        ) );

        add_filter( 'posts_fields', array( $this, 'posts_fields' ) );

        parent::__construct( $args );
    }

    public function posts_fields( $sql )
    {
        return "{$sql}, {$GLOBALS['wpdb']->terms}.name AS 'book_category'";
    }
}

그런 다음 다음 예에서 볼 수 있듯이 두 번째 / 추가 쿼리 를 실행할 수 있습니다 . 나중에 쿼리를 재설정하는 것을 잊지 마십시오.

$book_query = new My_Book_Query();
if ( $book_query->have_posts() )
{
    while ( $book_query->have_posts() )
    {
        $book_query->the_post();
        # ...do stuff...
    } // endwhile;
    wp_reset_postdata();
} // endif;

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.