다음을 통해 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);
}
답변
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');
답변
가장 많이 답한 답변으로 늦게 답변하면 쿼리가 중단되고 일부 주요 요점에서는 사실이 아닙니다.
주 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에게 다음을 지시합니다.
- 아래에서-more를 사용하여 URL을 쿼리 사양으로 구문 분석하십시오
WP->parse_request()
.- 이용 조건 태그에 의해 사용되는 모든 IS_ 변수를 설정
$wp_query->parse_query()
($wp_query
의 목적class WP_Query
에 정의된다wp-includes/query.php
). 이 함수의 이름에도 불구하고이 경우WP_Query->parse_query
실제로 우리를 위해 어떤 파싱도하지 않습니다.WP->parse_request()
.- 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;