query_posts ()가 더 이상 사용되지 않는 것으로 표시되는 이유는 무엇입니까?


15

query_posts()기술적으로 말하면 두 가지 기능 이 있습니다 . 하나 query_posts()는 실제로 WP_Query::query_posts()있고 다른 하나 는 글로벌 공간에 있습니다.

정신 이상에서 묻기 :

글로벌 query_posts()이 "악"인 경우 왜 더 이상 사용되지 않습니까?

또는 왜으로 표시되지 않는다 _doing_it_wong.


2
좋은 질문입니다! 왜 query_posts ()를 사용해서는 안되는지 모르는 다른 사람들을 위해 여기여기 에 좋은 입문서 Q & A가 있습니다.
Tim Malone

답변:


11

필수 질문

트리오로하자 발굴은 : ::query_posts, ::get_posts그리고 class WP_Query이해하는 ::query_posts더 나은.

워드 프레스에서 데이터를 얻는 초석은 WP_Query클래스입니다. 방법 모두 ::query_posts::get_posts클래스가 사용.

클래스 WP_Query에는 같은 이름의 메소드가 포함되어 있습니다. WP_Query::query_postsWP_Query::get_posts. 실제로 전역 메소드 만 고려하므로 혼동하지 마십시오.

여기에 이미지 설명을 입력하십시오

이해 WP_Query

라는 클래스 WP_Query는 2004 년에 다시 도입되었습니다. 2004 년에 where (우산) 마크가있는 모든 필드. 나중에 추가 필드가 추가되었습니다.

WP_Query구조 는 다음과 같습니다 .

class WP_Query (as in WordPress v4.7) 
    public $query; 
    public $query_vars = array(); 
    public $tax_query;
    public $meta_query = false;
    public $date_query = false;
    public $queried_object; 
    public $queried_object_id; 
    public $request;
    public $posts; 
    public $post_count = 0; 
    public $current_post = -1; 
    public $in_the_loop = false;
    public $post; 
    public $comments;
    public $comment_count = 0;
    public $current_comment = -1;
    public $comment;
    public $found_posts = 0;
    public $max_num_pages = 0;
    public $max_num_comment_pages = 0;
    public $is_single = false; 
    public $is_preview = false; 
    public $is_page = false; 
    public $is_archive = false; 
    public $is_date = false; 
    public $is_year = false; 
    public $is_month = false; 
    public $is_day = false; 
    public $is_time = false; 
    public $is_author = false; 
    public $is_category = false; 
    public $is_tag = false;
    public $is_tax = false;
    public $is_search = false; 
    public $is_feed = false; 
    public $is_comment_feed = false;
    public $is_trackback = false; 
    public $is_home = false; 
    public $is_404 = false; 
    public $is_embed = false;
    public $is_paged = false;
    public $is_admin = false; 
    public $is_attachment = false;
    public $is_singular = false;
    public $is_robots = false;
    public $is_posts_page = false;
    public $is_post_type_archive = false;
    private $query_vars_hash = false;
    private $query_vars_changed = true;
    public $thumbnails_cached = false;
    private $stopwords;
    private $compat_fields = array('query_vars_hash', 'query_vars_changed');
    private $compat_methods = array('init_query_flags', 'parse_tax_query');
    private function init_query_flags()

WP_Query 스위스 군용 칼입니다.

에 대한 몇 가지 WP_Query:

  • 전달한 인수를 통해 제어 할 수있는 것입니다.
  • 기본적으로 욕심이다
  • 그것은 반복 물질을 보유
  • 그것은 글로벌 공간 x2에 저장됩니다
  • 1 차 또는 2 차일 수 있습니다
  • 도우미 클래스를 사용합니다.
  • 편리한 pre_get_posts고리가 있습니다
  • 심지어 중첩 루프를 지원합니다
  • SQL 쿼리 문자열을 보유합니다.
  • 그것은 결과의 수를 보유
  • 그것은 결과를 보유
  • 가능한 모든 쿼리 인수 목록을 보유합니다.
  • 템플릿 플래그를 보유
  • ...

이 모든 것을 설명 할 수는 없지만 일부는 까다롭기 때문에 간단한 팁을 제공하겠습니다.

WP_Query 전달한 인수를 통해 제어 할 수있는 것

The list of the arguments
---
 attachment
 attachment_id
 author
 author__in
 author__not_in
 author_name
 cache_results
 cat
 category__and
 category__in
 category__not_in
 category_name
 comments_per_page
 day
 embed
 error
 feed
 fields
 hour
 ignore_sticky_posts
 lazy_load_term_meta
 m
 menu_order
 meta_key
 meta_value
 minute
 monthnum
 name
 no_found_rows
 nopaging
 order
 p
 page_id
 paged
 pagename
 post__in
 post__not_in
 post_name__in
 post_parent
 post_parent__in
 post_parent__not_in
 post_type
 posts_per_page
 preview
 s
 second
 sentence
 static
 subpost
 subpost_id
 suppress_filters
 tag
 tag__and
 tag__in
 tag__not_in
 tag_id
 tag_slug__and
 tag_slug__in
 tb
 title
 update_post_meta_cache
 update_post_term_cache
 w
 year

WordPress 버전 4.7의이 목록은 미래에 확실히 변경 될 것입니다.

이것은 WP_Query인수 에서 객체를 만드는 최소한의 예입니다 .

// WP_Query arguments
$args = array ( /* arguments*/ );
// creating the WP_Query object
$query = new WP_Query( $args );
// print full list of arguments WP_Query can take
print ( $query->query_vars );

WP_Query 탐욕 스럽다

아이디어에 만든 get all you can이 같이 초기 가능한 모든 데이터를하기로 결정 워드 프레스 개발자 성능 좋은 . 기본적으로 쿼리가 데이터베이스에서 10 개의 게시물을 가져 오면 별도의 쿼리를 통해 이러한 게시물에 대한 용어 및 메타 데이터도 가져옵니다. 용어 및 메타 데이터가 캐시됩니다 (프리 페치).

캐싱은 단일 요청 수명을위한 것입니다.

사용자가 설정 한 경우 캐싱을 사용하지 않도록 설정할 수 있습니다 update_post_meta_cacheupdate_post_term_cachefalse, 설정하면서 WP_Query인수를. 캐싱을 사용하지 않으면 요청시에만 데이터베이스에서 데이터가 요청됩니다.

대부분의 WordPress 블로그에서 캐싱은 잘 작동하지만 캐싱을 비활성화 할 수있는 경우가 있습니다.

WP_Query 헬퍼 클래스 사용

WP_Query필드 를 확인 하면 다음 세 가지가 있습니다.

public $tax_query;
public $meta_query;
public $date_query;

앞으로 새로운 것을 추가하는 것을 상상할 수 있습니다.

여기에 이미지 설명을 입력하십시오

WP_Query 반복 물질을 보유

이 코드에서 :

$query = new WP_Query( $args )
if ( $query->have_posts() ) {
        while ( $query->have_posts() ) {
            $query->the_post();

당신은이 나타날 수 있습니다 WP_Query당신은 반복 할 수있는 물질이있다. 도우미 방법도 있습니다. 당신은 while루프를 설정했습니다 .

노트. for그리고 while루프는 의미 적으로 동일합니다.

WP_Query 기본 및 보조

WordPress에는 하나의 기본 쿼리 와 0 개 이상의 보조 쿼리가 있습니다.

기본 쿼리를 가질 수는 없지만이 기사의 범위를 벗어납니다.

기본 쿼리 로 알려진 주 쿼리 또는 일반 쿼리 . 보조 쿼리사용자 지정 쿼리 라고도 합니다 .

WordPress는 WP_Rewrite클래스를 일찍 사용 하여 URL을 기반으로 쿼리 인수를 만듭니다. 이러한 인수를 기반으로 전역 공간에 두 개의 동일한 객체를 저장합니다. 둘 다 기본 쿼리를 보유합니다.

global $wp_query   @since WordPress 1.5
global $wp_the_query @since WordPress 2.1

메인 쿼리 를 말할 때 이러한 변수를 생각합니다. 다른 쿼리는 보조 또는 사용자 정의라고 할 수 있습니다.

사용 중 완전히 합법적 global $wp_query이나 $GLOBALS['wp_query'],하지만 두 번째 표기법을 사용하는 것이 훨씬 더 주목할만한, 그리고 기능의 범위 내 여분의 줄을 입력 저장합니다.

$GLOBALS['wp_query']그리고 $GLOBALS['wp_the_query']별도의 개체입니다. $GLOBALS['wp_the_query']냉동 상태로 유지해야합니다.

WP_Query편리한 pre_get_posts고리가 있습니다.

이것이 행동 후크입니다. 모든 WP_Query 인스턴스에 적용됩니다 . 당신은 그것을 다음과 같이 부릅니다.

add_action( 'pre_get_posts', function($query){

 if ( is_category() && $query->is_main_query() ) {
    // set your improved arguments
    $query->set( ... );  
    ...  
 }

 return $query;  
});

이 후크는 훌륭하며 모든 쿼리 인수를 변경할 수 있습니다.

읽을 수있는 내용 은 다음과 같습니다 .

쿼리 변수 개체가 생성 된 후 실제 쿼리가 실행되기 전에 실행됩니다.

따라서이 후크는 인수 관리자이지만 새 WP_Query객체를 만들 수는 없습니다 . 기본 쿼리와 보조 쿼리가 하나 있으면 pre_get_posts세 번째 쿼리를 만들 수 없습니다. 또는 하나의 기본 서버가있는 경우 보조 서버를 만들 수 없습니다.

기본 쿼리를 변경 해야하는 경우 request후크를 사용할 수도 있습니다.

WP_Query 중첩 루프 지원

이 시나리오는 플러그인을 사용하고 템플리트에서 플러그인 함수를 호출하는 경우 발생할 수 있습니다.

다음은 WordPress에 중첩 루프에 대해서도 도우미 기능이있는 쇼케이스 예입니다.

global $id;
while ( have_posts() ) : the_post(); 

    // the custom $query
    $query = new WP_Query( array(   'posts_per_page' => 5   ) );    
    if ( $query->have_posts() ) {

        while ( $query->have_posts() ) : $query->the_post();            
            echo '<li>Custom ' . $id . '. ' . get_the_title() . '</li>';
        endwhile;       
    }   

    wp_reset_postdata();
    echo '<li>Main Query ' . $id . '. ' . get_the_title() . '</li>';

endwhile;

테마 단위 테스트 데이터를 설치 한 후 출력은 다음과 같습니다 .

Custom 100. Template: Sticky
Custom 1. Hello world!
Custom 10. Markup: HTML Tags and Formatting
Custom 11. Markup: Image Alignment
Custom 12. Markup: Text Alignment
Custom 13. Markup: Title With Special Characters
Main Query 1. Hello world!

사용자 정의 $ 쿼리에서 5 개의 게시물을 요청했지만 끈적 인 게시물이 이어지기 때문에 6을 반환합니다. wp_reset_postdata이전 예제에 없는 경우 출력이 $GLOBALS['post']유효하지 않기 때문에 이와 같이 출력됩니다 .

Custom 1001. Template: Sticky
Custom 1. Hello world!
Custom 10. Markup: HTML Tags and Formatting
Custom 11. Markup: Image Alignment
Custom 12. Markup: Text Alignment
Custom 13. Markup: Title With Special Characters
Main Query 13. Markup: Title With Special Characters

WP_Querywp_reset_query기능을

이것은 리셋 버튼과 같습니다. $GLOBALS['wp_the_query']플러그인 또는 테마를 변경해서는 안됩니다.

wp_reset_query수행 할 작업 은 다음과 같습니다 .

function wp_reset_query() {
    $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];
    wp_reset_postdata();
}

비고 get_posts

get_posts ~처럼 보인다

File: /wp-includes/post.php
1661: function get_posts( $args = null ) {
1662:   $defaults = array(
1663:       'numberposts' => 5,
1664:       'category' => 0, 'orderby' => 'date',
1665:       'order' => 'DESC', 'include' => array(),
1666:       'exclude' => array(), 'meta_key' => '',
1667:       'meta_value' =>'', 'post_type' => 'post',
1668:       'suppress_filters' => true
1669:   );
... // do some argument parsing
1685:   $r['ignore_sticky_posts'] = true;
1686:   $r['no_found_rows'] = true;
1687: 
1688:   $get_posts = new WP_Query;
1689:   return $get_posts->query($r);

줄 번호는 나중에 변경 될 수 있습니다.

그것은 단지입니다 래퍼 주위에 WP_Query반환 쿼리 객체 게시물.

ignore_sticky_posts진정한 수단 세트는 끈적 게시물은 자연적인 위치에 표시 할 수 있습니다. 전면에 끈끈한 기둥이 없습니다. 다른 no_found_rows값을 true로 설정하면 워드 프레스 데이터베이스 API가 SQL_CALC_FOUND_ROWS페이지 매김을 구현하기 위해 사용하지 않으므로 데이터베이스 의로드가 줄어드는 횟수를 입니다.

페이지 매김이 필요하지 않을 때 편리합니다. 이제이 쿼리를 통해이 기능을 모방 할 수 있음을 이해합니다.

$args = array ( 'ignore_sticky_posts' => true, 'no_found_rows' => true);
$query = new WP_Query( $args );
print( $query->request );

해당 SQL 요청은 다음과 같습니다.

SELECT wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') ORDER BY wp_posts.post_date DESC LIMIT 0, 10

우리가 지금 가지고있는 것을 이전 SQL 요청과 비교하십시오 SQL_CALC_FOUND_ROWS.

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private')  ORDER BY wp_posts.post_date DESC LIMIT 0, 10

없는 요청 SQL_CALC_FOUND_ROWS은 더 빠를 것입니다.

비고 query_posts

팁 : 2004 년 처음에는 global $wp_query. WordPress 2.1 버전부터 제공 $wp_the_query됩니다. 팁 : $GLOBALS['wp_query']$GLOBALS['wp_the_query']별도의 개체입니다.

query_posts()입니다 WP_Query래퍼. 기본 WP_Query객체에 대한 참조를 반환하고 동시에을 설정합니다 global $wp_query.

File: /wp-includes/query.php
function query_posts($args) {
    $GLOBALS['wp_query'] = new WP_Query();
    return $GLOBALS['wp_query']->query($args);
}

PHP4에서는 객체를 포함한 모든 것이 가치에 의해 전달되었습니다. query_posts이 같은 :

File: /wp-includes/query.php (WordPress 3.1)
function &query_posts($args) {
    unset($GLOBALS['wp_query']);
    $GLOBALS['wp_query'] =& new WP_Query();
    return $GLOBALS['wp_query']->query($args);
}

하나의 기본 쿼리와 하나의 보조 쿼리가있는 일반적인 시나리오에는 다음 세 가지 변수가 있습니다.

$GLOBALS['wp_the_query'] 
$GLOBALS['wp_query'] // should be the copy of first one
$custom_query // secondary

이 세 가지 각각에 1M의 메모리가 필요하다고 가정 해 봅시다. 총 메모리는 3M입니다. 우리가 사용하는 경우 query_posts, $GLOBALS['wp_query']해제하고 다시 생성됩니다.

PHP5 $GLOBALS['wp_query']와 마찬가지로 PHP5 +는 객체를 비우는 것이 현명해야합니다 .unset($GLOBALS['wp_query']);

function query_posts($args) {
    $GLOBALS['wp_query'] = new WP_Query();
    return $GLOBALS['wp_query']->query($args);
}

결과적으로 query_posts총 2M의 메모리를 get_posts소비하고 3M의 메모리 를 소비합니다.

의 주 query_posts우리는 실제 개체를 반환하지만, 객체에 대한 참조되지 않습니다.

에서 php.net 하십시오 PHP 참조 번호는 동일한 값으로 기록하는 두 가지 변수를 허용하는 별명이다. PHP 5부터 객체 변수는 객체 자체를 더 이상 값으로 포함하지 않습니다. 객체 접근자가 실제 객체를 찾을 수있게하는 객체 식별자 만 포함합니다. 객체를 인수로 보내거나 다른 변수에 반환하거나 할당하면 다른 변수는 별칭이 아닙니다. 동일한 객체를 가리키는 식별자의 사본을 보유합니다.

또한 PHP5 +에서 assign (=) 연산자는 똑똑합니다. 하드 카피가 아닌 얕은 카피 를 사용 합니다. 이와 같이 쓰면 $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];동일한 객체 유형을 공유하므로 전체 객체가 아닌 데이터 만 복사됩니다.

여기에 하나의 예가 있습니다

print( md5(serialize($GLOBALS['wp_the_query']) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
query_posts( '' );
print( md5(serialize($GLOBALS['wp_the_query']) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );

결과 :

f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
d6db1c6bfddac328442e91b6059210b5

쿼리를 재설정하십시오.

print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
query_posts( '' );
wp_reset_query();
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );

결과 :

f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef
f14153cab65abf1ea23224a1068563ef

사용하더라도 문제가 발생할 수 있습니다 WP_Query

print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
global $wp_query;
$wp_query = new WP_Query( array( 'post_type' => 'post' ) );   
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );

물론 해결책은 wp_reset_query기능을 다시 사용 하는 것입니다.

print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );
global $wp_query;
$wp_query = new WP_Query( array( 'post_type' => 'post' ) );
wp_reset_query();
print( md5(serialize($GLOBALS['wp_the_query'] ) ) );
print( md5(serialize($GLOBALS['wp_query'] ) ) );

이것이 query_posts메모리 관점에서 더 좋을 것이라고 생각하는 이유 입니다. 그러나 항상 wp_reset_query속임수를 쓰십시오.


10

의 사용 중단을 제안하기 위해 새로운 trac 티켓 티켓 # 36874을 만들었습니다 query_posts(). 받아 들일지 여부는 좋은 질문입니다.

진짜 큰 문제 query_posts()는 플러그인과 테마에서 여전히 널리 사용되는 이유 입니다.하지만 절대로 사용 해서는 안되는 주제에 대한 글이 정말 훌륭 했지만. WPSE에 대한 가장 멋진 게시물은 다음과 같습니다.

지원 중단! == 제거 이므로 지원 중단 query_posts()으로 인해 품질이 좋지 않은 개발자 및 WordPress를 모르고 품질이 낮은 자습서를 가이드 라인으로 사용하는 사람들은 사용을 중단하지 않습니다. 사람들이 사용하는 경우 그냥 몇 가지 증거로, 우리는 여전히 여기에 얼마나 많은 질문을받을 수 있나요 caller_get_posts에서 WP_Query? 수년 동안 사용되지 않습니다.

그러나 더 이상 사용되지 않는 함수와 인수는 핵심 개발자가 적합하다고 생각할 때 언제든지 제거 할 수 있지만 query_posts()수백만 개의 사이트가 손상 될 가능성이 거의 없습니다 . 따라서 우리는 아마도 완전히 제거되지 않을 것입니다. query_posts()이는 아마도 더 이상 사용되지 않을 것이라는 사실로 이어질 수 있습니다.

이것은 시작점이지만 WordPress에서 무언가를 사용하지 않아도 사용이 중단되지 않는다는 것을 기억해야합니다.

업데이트 2016 년 5 월 19 일

내가 올린 티켓은 이제 닫히고 4 살짜리 티켓 과 중복으로 표시됩니다.이 티켓은 wontfix 로 닫히고 다시 열렸지만 여전히 열려 있고 해결되지 않은 상태로 남아 있습니다.

핵심 개발자들이이 오래된 충실한 작은 악에 매달린 것 같습니다. 관심있는 모든 사람, 여기에 4 년 된 중복 티켓이 있습니다.


그들이 티켓 core.trac.wordpress.org/ticket/36874 를 닫은 이유는 무엇 입니까? 이 질문에 대한 티켓이 티켓 1 : 1
prosti

@prosti이 문제가 이미 제기되었으므로 중복 된 것으로 표시되었습니다. 4 년 전 여기에서 발견되었습니다 .
Howdy_McGee

3

[어떻게 울부 짖다]

이 시점에서 진정으로 더 이상 사용되지 않는 것은 핵심 철학입니다. 사용 중단 통지는 기쁘지만 기능이 실제로 어느 시점에서 삭제되지 않으면 무시됩니다. 에 개발되지 않은 많은 사람들이 WP_DEBUG있으며 실제 파손되지 않으면 통지를 통지하지 않습니다.

OTOH 손,이 기능은 goto문장 과 같습니다 . 개인적으로 나는 (더 작은 정의를 위해 기대 한) 결코 사용 goto하지 않았지만 기본적으로 악하지 않은 상황을 가리키는 주장을 이해할 수 있습니다. 동일이와 함께가는 query_posts이 모든 전역 간단한 루프를 만드는 데 필요한 설정하는 간단한 방법이며, 아약스에 유용 또는 휴식-API 컨텍스트를 할 수 있습니다. 나는 그러한 맥락에서도 그것을 사용하지 않을 것이지만, 거기에서 코딩 스타일의 문제가 아니라 기능 자체가 악하다는 것을 알 수 있습니다.

좀 더 깊이 들어가면 주요 문제는 전 세계를 전혀 설정해야한다는 것입니다. 이것이 문제를 설정하는 데 도움이되는 주요 문제는 아닙니다.


그리고 비교를 query_posts위해 보조 쿼리보다 실제로 속도가 느립니다 (주 쿼리가 아님).
prosti

@ prosti, wp_query를 설정하고 실행하기 때문에 얼마나 느릴 수 있습니까? 약간의 오버 헤드가 있지만 여기서는 밀리 초를 이야기 할 것입니다. 물론 이것은 WP가 기본적으로 쿼리를 제공하지 않는 장소에서 사용한다고 가정합니다. 그것이 나쁜 곳에서, query_posts그 자체가 아니라 WP
가로
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.