상현에 하루하루
개발자의 하루

추천 게시물 올바르게 만들기

( 업데이트: )

추천 게시물을 얻기 위해 데이터베이스를 쿼리하려는 경우, 우리는 모두 새로운 WP_Query를 만들고 루프를 통해 다음과 같이 해야 할 때라는 것을 알고 있습니다.

$featured_args = array(
    'post__in' => get_option( 'sticky_posts' ),
    'post_status' => 'publish',
    'no_found_rows' => true
);

// Thre Featured posts query.
$featured = new WP_Query( $featured_args );

// Proceed only if published posts with thumbnails exist
if ( $featured->have_posts() ) {
    while ( $featured->have_posts() ) {
        $featured->the_post();
        if ( has_post_thumbnail( $featured->post->ID ) ) {
            // do stuff here
        }
    }
    // Reset the post data
    wp_reset_postdata();
}Code language: PHP (php)

Awesome! 두 개의 쿼리, 충돌 없음 세상 모든 것이 옳습니다. wp_reset_postdata()를 사용하는 것을 기억하고 있습니까? 😉 그렇지 않은 경우 모든 새로운 WP_Query$post 전역을 방금 실행한 루프의 반복으로 대체하기 때문입니다. 재설정하지 않으면 메인 루프 쿼리에서 추천 게시물 쿼리의 $post 데이터로 끝날 수 있습니다.

query_posts()를 기억하십니까? $wp_query를 대체하고 $wp_the_query를 다시 찾지 않습니다.

그렇다면 이제 추천 게시물 쿼리가 완료되고 추천 게시물을 모두 버린 후 메인 루프에서 추천 게시물을 제외하고 싶다면?

query_posts()를 사용하고 기본 $wp_query 루프를 교체하려는 것이 합리적입니다. 맞습니까?
내 말은, 메인 루프 쿼리가 발생하기 전에 추천 게시물 쿼리를 실행하지 않았다면 제외할 대상을 어떻게 알겠습니까?

WP_Querypre_get_posts라는 작업으로 이를 매우 우아하게 처리하도록 설계되었습니다.

우리는 메인 루프, 추천 게시물, 제외할 query_posts()을 쿼리하는 대신 기본 쿼리를 미리 수정하고 원하지 않는 것을 제외하고 평소와 같이 추천 쿼리를 실행할 수 있습니다.

/**
 * 홈 페이지 게시물을 필터링하고 기능을 갖춘 게시물 ID를 제거한다
 * 포스트 배열을 얻기 전에 `pre_get_posts` 동작으로 쿼리의 매개변수를 변경합니다.
 *
 * @global array $featured_post_id
 * @param WP_Query $query
 * @return WP_Query Possibly modified WP_query
 */
function itheme2_home_posts( $query = false ) {
    // 홈 페이지, 쿼리가 아닌경우, 메인 쿼리가 아닌경우, featured 포스트가 아님
  if ( ! is_home() || !is_a( $query, 'WP_Query' ) || ! $query->is_main_query() || ! itheme2_featuring_posts() )
        return;

    // 메인 쿼라에서 featured 포스트를 제외
    $query->set( 'post__not_in' itheme2_featuring_posts() );

    // 'pre_get_posts'는 byref 작업입니다.
    // 쿼리를 직접 수정하고 있습니다.
    // 그렇기에 우리는 아무것도 반환하지 않습니다.
}
add_action( 'pre_get_posts', 'itheme2_home_posts' );

/**
 * 게시물이있는 게시물이 우리의 조건을 충족하는지 확인하려면 테스트하십시오.
 *
 * 현재 조건은:
 * - sticky posts
 * - with featured thumbnails
 *
 * 루프의 결과를 일시적으로 저장하여 실행을 방지합니다.
 * 모든 페이지로드에 대한 추가 쿼리. 결과는 POST ID의 배열입니다.
 * 위의 결과를 일치시킵니다. 이것은 우리에게 특집을 통해 루프를 루프 할 수있는 빠른 방법을 제공합니다.
 * 나중에 추가 시간을 쿼리 할 필요없이 나중에 다시 게시합니다.
 */
function itheme2_featuring_posts() {
    if ( false === ( $featured_post_ids = get_transient( 'featured_post_ids' ) ) ) {
        // sticky 게시물이있는 경우에만 계속하십시오
        if ( get_option( 'sticky_posts' ) ) { 
            $featured_args = array(
                'post__in'      => get_option( 'sticky_posts' ),
                'post_status'   => 'publish',
                'no_found_rows' => true
            );
            // featured 포스트 쿼리
            $featured = new WP_Query( $featured_args );

            // thumbnail이 있는 경우에만 계속 진행
            if ( $featured->have_posts() ) {
                while ( $featured->have_posts() ) {
                    $featured->the_post();
                    if ( has_post_thumbnail( $featured->post->ID ) ) {
                        $featured_post_ids[] = $featured->post->ID;
                    }
                }
                set_transient( 'featured_post_ids', $featured_post_ids );
            }
        }

        // 포스트 ID를 캐시 또는 루프에서 반환하십시오.
        return $featured_post_ids;
}Code language: PHP (php)

다음 코드를 읽어 보자면

  1. 기본 쿼리를 필터링합니다.
  2. 홈페이지에 있는 경우에만 진행하십시오
  3. 쿼리가 엉망이 아닌 경우에만 진행하십시오
  4. 기본 쿼리를 필터링하려는 경우에만 진행하십시오
  5. 실제로 추천 게시물이 있는 경우에만 진행하십시오
  6. 추천 게시물? sticky 옵션을 확인해보자.
  7. 게시물이 있는 경우 게시물 쿼리
  8. (이 시점에서 WP_Query가 다시 실행되고 pre_get_posts 필터도 실행됩니다. 위의 검사 덕분에 추천 게시물에 대한 쿼리는 항목을 제외해야 해서 오염되지 않습니다.
  9. 우리가 얻은 각 게시물 ID를 가져와 배열에 저장합니다.
  10. 페이지를 로드 할 떄마다 이 작업을 계속 수정하지 않도록 해당 배열을 캐시로 저장합니다.
  11. 추천 게시물을 끝내고 다시 기본 쿼리 필터로 돌아갑니다.
  12. 기본 쿼리에서 방금 얻은 게시물 ID를 제외합니다.
  13. 수정된 기본 쿼리 변수를 반환합니다.
  14. 나머지는 WordPress가 처리하도록 합니다.

잠재적 비용이 많이 드는 WP_Query 객체를 생성하지 않도록 약간의 로직을 스스로 설계할 수 있습니다.