query_posts()
기술적으로 말하면 두 가지 기능 이 있습니다 . 하나 query_posts()
는 실제로 WP_Query::query_posts()
있고 다른 하나 는 글로벌 공간에 있습니다.
정신 이상에서 묻기 :
글로벌 query_posts()
이 "악"인 경우 왜 더 이상 사용되지 않습니까?
또는 왜으로 표시되지 않는다 _doing_it_wong
.
query_posts()
기술적으로 말하면 두 가지 기능 이 있습니다 . 하나 query_posts()
는 실제로 WP_Query::query_posts()
있고 다른 하나 는 글로벌 공간에 있습니다.
정신 이상에서 묻기 :
글로벌 query_posts()
이 "악"인 경우 왜 더 이상 사용되지 않습니까?
또는 왜으로 표시되지 않는다 _doing_it_wong
.
답변:
트리오로하자 발굴은 : ::query_posts
, ::get_posts
그리고 class WP_Query
이해하는 ::query_posts
더 나은.
워드 프레스에서 데이터를 얻는 초석은 WP_Query
클래스입니다. 방법 모두 ::query_posts
와 ::get_posts
클래스가 사용.
클래스
WP_Query
에는 같은 이름의 메소드가 포함되어 있습니다.WP_Query::query_posts
및WP_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
:
pre_get_posts
고리가 있습니다이 모든 것을 설명 할 수는 없지만 일부는 까다롭기 때문에 간단한 팁을 제공하겠습니다.
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_cache
과 update_post_term_cache
에 false
, 설정하면서 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_Query
이 wp_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
속임수를 쓰십시오.
의 사용 중단을 제안하기 위해 새로운 trac 티켓 티켓 # 36874을 만들었습니다 query_posts()
. 받아 들일지 여부는 좋은 질문입니다.
진짜 큰 문제 query_posts()
는 플러그인과 테마에서 여전히 널리 사용되는 이유 입니다.하지만 절대로 사용 해서는 안되는 주제에 대한 글이 정말 훌륭 했지만. WPSE에 대한 가장 멋진 게시물은 다음과 같습니다.
지원 중단! == 제거 이므로 지원 중단 query_posts()
으로 인해 품질이 좋지 않은 개발자 및 WordPress를 모르고 품질이 낮은 자습서를 가이드 라인으로 사용하는 사람들은 사용을 중단하지 않습니다. 사람들이 사용하는 경우 그냥 몇 가지 증거로, 우리는 여전히 여기에 얼마나 많은 질문을받을 수 있나요 caller_get_posts
에서 WP_Query
? 수년 동안 사용되지 않습니다.
그러나 더 이상 사용되지 않는 함수와 인수는 핵심 개발자가 적합하다고 생각할 때 언제든지 제거 할 수 있지만 query_posts()
수백만 개의 사이트가 손상 될 가능성이 거의 없습니다 . 따라서 우리는 아마도 완전히 제거되지 않을 것입니다. query_posts()
이는 아마도 더 이상 사용되지 않을 것이라는 사실로 이어질 수 있습니다.
이것은 시작점이지만 WordPress에서 무언가를 사용하지 않아도 사용이 중단되지 않는다는 것을 기억해야합니다.
내가 올린 티켓은 이제 닫히고 4 살짜리 티켓 과 중복으로 표시됩니다.이 티켓은 wontfix 로 닫히고 다시 열렸지만 여전히 열려 있고 해결되지 않은 상태로 남아 있습니다.
핵심 개발자들이이 오래된 충실한 작은 악에 매달린 것 같습니다. 관심있는 모든 사람, 여기에 4 년 된 중복 티켓이 있습니다.
[어떻게 울부 짖다]
이 시점에서 진정으로 더 이상 사용되지 않는 것은 핵심 철학입니다. 사용 중단 통지는 기쁘지만 기능이 실제로 어느 시점에서 삭제되지 않으면 무시됩니다. 에 개발되지 않은 많은 사람들이 WP_DEBUG
있으며 실제 파손되지 않으면 통지를 통지하지 않습니다.
OTOH 손,이 기능은 goto
문장 과 같습니다 . 개인적으로 나는 (더 작은 정의를 위해 기대 한) 결코 사용 goto
하지 않았지만 기본적으로 악하지 않은 상황을 가리키는 주장을 이해할 수 있습니다. 동일이와 함께가는 query_posts
이 모든 전역 간단한 루프를 만드는 데 필요한 설정하는 간단한 방법이며, 아약스에 유용 또는 휴식-API 컨텍스트를 할 수 있습니다. 나는 그러한 맥락에서도 그것을 사용하지 않을 것이지만, 거기에서 코딩 스타일의 문제가 아니라 기능 자체가 악하다는 것을 알 수 있습니다.
좀 더 깊이 들어가면 주요 문제는 전 세계를 전혀 설정해야한다는 것입니다. 이것이 문제를 설정하는 데 도움이되는 주요 문제는 아닙니다.
query_posts
위해 보조 쿼리보다 실제로 속도가 느립니다 (주 쿼리가 아님).
query_posts
그 자체가 아니라 WP