wordpress-文章对象

使用wordpress遍历文章循环功能时,一直都是复制粘贴以下代码,在此基础上调整功能。由于不了解,每次使用时心里不踏实,徒增神秘感。因此,这次下决心了解此机制,非祛魅不可。

$args = array(
    'post_type' => 'fanhua_history',
    'posts_per_page' => 3
);
$query = new WP_Query($args);

if ($query->have_posts()) {
    echo '有文章需要处理:';
    while ($query->have_posts()) {
        $query->the_post();
        echo '<h2>'. get_the_title(). '</h2>';
    }
} else {
    echo '没有找到符合条件的文章。';
}
wp_reset_postdata();

◆ 查询文章返回结果

WP_Query Object
(
    [query] => Array
        (
            [post_type] => fanhua_history
            [posts_per_page] => -1
        )

    [query_vars] => Array
        (
            [post_type] => fanhua_history
            [posts_per_page] => -1
            [error] =>
            [m] =>
            [p] => 0
            [post_parent] =>
            [subpost] =>
            [subpost_id] =>
            [attachment] =>
            [attachment_id] => 0
            [name] =>
            [pagename] =>
            [page_id] => 0
            [second] =>
            [minute] =>
            [hour] =>
            [day] => 0
            [monthnum] => 0
            [year] => 0
            [w] => 0
            [category_name] =>
            [tag] =>
            [cat] =>
            [tag_id] =>
            [author] =>
            [author_name] =>
            [feed] =>
            [tb] =>
            [paged] => 0
            [meta_key] =>
            [meta_value] =>
            [preview] =>
            [s] =>
            [sentence] =>
            [title] =>
            [fields] =>
            [menu_order] =>
             =>
            [category__in] => Array ()
            [category__not_in] => Array()
            [category__and] => Array()
            [post__in] => Array()
            [post__not_in] => Array()
            [post_name__in] => Array()
            [tag__in] => Array()
            [tag__not_in] => Array()
            [tag__and] => Array()
            [tag_slug__in] => Array()
            [tag_slug__and] => Array()
            [post_parent__in] => Array()
            [post_parent__not_in] => Array()
            [author__in] => Array()
            [author__not_in] => Array()
            [search_columns] => Array()
            [ignore_sticky_posts] =>
            [suppress_filters] =>
            [cache_results] => 1
            [update_post_term_cache] => 1
            [update_menu_item_cache] =>
            [lazy_load_term_meta] => 1
            [update_post_meta_cache] => 1
            [nopaging] => 1
            [comments_per_page] => 50
            [no_found_rows] =>
            [order] => DESC
        )

    [tax_query] => WP_Tax_Query Object
        (
            [queries] => Array()
            [relation] => AND
            [table_aliases:protected] => Array()
            [queried_terms] => Array()
            [primary_table] => xs_3_posts
            [primary_id_column] => ID
        )

    [meta_query] => WP_Meta_Query Object
        (
            [queries] => Array()
            [relation] =>
            [meta_table] =>
            [meta_id_column] =>
            [primary_table] =>
            [primary_id_column] =>
            [table_aliases:protected] => Array()
            [clauses:protected] => Array()
            [has_or_relation:protected] =>
        )

    [date_query] =>
    [request] => 
            SELECT xs_3_posts.* FROM xs_3_posts
            WHERE 1 = 1
              AND (
                (
                    xs_3_posts.post_type = 'fanhua_history'
                    AND (xs_3_posts.post_status = 'publish' OR xs_3_posts.post_status = 'private')
                    )
                )
            ORDER BY xs_3_posts.post_date DESC

    [posts] => Array
        (
            [0] => WP_Post Object
                (
                    [ID] => 74
                    [post_author] => 1
                    [post_date] => 2025-02-27 16:17:12
                    [post_date_gmt] => 2025-02-27 08:17:12
                    [post_content] =>
                    [post_title] => X先生的打字机
                    [post_excerpt] =>
                    [post_status] => publish
                    [comment_status] => closed
                    [ping_status] => closed
                    [post_password] =>
                    [post_name] => x%e5%85%88%e7%94%9f%e7%9a%84%e6%89%93%e5%ad%97%e6%9c%ba
                    [to_ping] =>
                    [pinged] =>
                    [post_modified] => 2025-02-27 16:17:12
                    [post_modified_gmt] => 2025-02-27 08:17:12
                    [post_content_filtered] =>
                    [post_parent] => 0
                    [guid] => https://example3.chenzhuzhen.cn/?post_type=fanhua_history&p=74
                    [menu_order] => 0
                    [post_type] => fanhua_history
                    [post_mime_type] =>
                    [comment_count] => 0
                    [filter] => raw
                )

            [1] => WP_Post Object
                (
                    [ID] => 73
                    [post_author] => 1
                    [post_date] => 2025-02-27 16:16:28
                    [post_date_gmt] => 2025-02-27 08:16:28
                    [post_content] =>
                    [post_title] => L女士的首饰音乐盒
                    [post_excerpt] =>
                    [post_status] => publish
                    [comment_status] => closed
                    [ping_status] => closed
                    [post_password] =>
                    [post_name] => l%e5%a5%b3%e5%a3%ab%e7%9a%84%e9%a6%96%e9%a5%b0%e9%9f%b3%e4%b9%90%e7%9b%92
                    [to_ping] =>
                    [pinged] =>
                    [post_modified] => 2025-02-27 16:16:28
                    [post_modified_gmt] => 2025-02-27 08:16:28
                    [post_content_filtered] =>
                    [post_parent] => 0
                    [guid] => https://example3.chenzhuzhen.cn/?post_type=fanhua_history&p=73
                    [menu_order] => 0
                    [post_type] => fanhua_history
                    [post_mime_type] =>
                    [comment_count] => 0
                    [filter] => raw
                )

            [2] => WP_Post Object
                (
                    [ID] => 72
                    [post_author] => 1
                    [post_date] => 2025-02-27 16:15:49
                    [post_date_gmt] => 2025-02-27 08:15:49
                    [post_content] =>
                    [post_title] => K先生的金利来考克箱
                    [post_excerpt] =>
                    [post_status] => publish
                    [comment_status] => closed
                    [ping_status] => closed
                    [post_password] =>
                    [post_name] => k%e5%85%88%e7%94%9f%e7%9a%84%e9%87%91%e5%88%a9%e6%9d%a5%e8%80%83%e5%85%8b%e7%ae%b1
                    [to_ping] =>
                    [pinged] =>
                    [post_modified] => 2025-02-27 16:15:49
                    [post_modified_gmt] => 2025-02-27 08:15:49
                    [post_content_filtered] =>
                    [post_parent] => 0
                    [guid] => https://example3.chenzhuzhen.cn/?post_type=fanhua_history&p=72
                    [menu_order] => 0
                    [post_type] => fanhua_history
                    [post_mime_type] =>
                    [comment_count] => 0
                    [filter] => raw
                )

            [3] => WP_Post Object
                (
                    [ID] => 63
                    [post_author] => 1
                    [post_date] => 2025-02-27 16:13:30
                    [post_date_gmt] => 2025-02-27 08:13:30
                    [post_content] =>
                    [post_title] => 小Y奶奶的盘子“宝物”
                    [post_excerpt] =>
                    [post_status] => publish
                    [comment_status] => closed
                    [ping_status] => closed
                    [post_password] =>
                    [post_name] => %e5%b0%8fy%e5%a5%b6%e5%a5%b6%e7%9a%84%e7%9b%98%e5%ad%90%e5%ae%9d%e7%89%a9
                    [to_ping] =>
                    [pinged] =>
                    [post_modified] => 2025-02-27 16:13:30
                    [post_modified_gmt] => 2025-02-27 08:13:30
                    [post_content_filtered] =>
                    [post_parent] => 0
                    [guid] => https://example3.chenzhuzhen.cn/?post_type=fanhua_history&p=63
                    [menu_order] => 0
                    [post_type] => fanhua_history
                    [post_mime_type] =>
                    [comment_count] => 0
                    [filter] => raw
                )

            [4] => WP_Post Object
                (
                    [ID] => 64
                    [post_author] => 1
                    [post_date] => 2025-02-27 16:12:39
                    [post_date_gmt] => 2025-02-27 08:12:39
                    [post_content] =>
                    [post_title] => 监制、总导演王家卫三十年珍藏绍兴老酒
                    [post_excerpt] =>
                    [post_status] => publish
                    [comment_status] => closed
                    [ping_status] => closed
                    [post_password] =>
                    [post_name] => 64
                    [to_ping] =>
                    [pinged] =>
                    [post_modified] => 2025-02-27 16:12:44
                    [post_modified_gmt] => 2025-02-27 08:12:44
                    [post_content_filtered] =>
                    [post_parent] => 0
                    [guid] => https://example3.chenzhuzhen.cn/?post_type=fanhua_history&p=64
                    [menu_order] => 0
                    [post_type] => fanhua_history
                    [post_mime_type] =>
                    [comment_count] => 0
                    [filter] => raw
                )

            [5] => WP_Post Object
                (
                    [ID] => 65
                    [post_author] => 1
                    [post_date] => 2025-02-27 16:11:44
                    [post_date_gmt] => 2025-02-27 08:11:44
                    [post_content] =>
                    [post_title] => 原著作者金宇澄老师珍贵旧物
                    [post_excerpt] =>
                    [post_status] => publish
                    [comment_status] => closed
                    [ping_status] => closed
                    [post_password] =>
                    [post_name] => 65
                    [to_ping] =>
                    [pinged] =>
                    [post_modified] => 2025-02-27 16:11:48
                    [post_modified_gmt] => 2025-02-27 08:11:48
                    [post_content_filtered] =>
                    [post_parent] => 0
                    [guid] => https://example3.chenzhuzhen.cn/?post_type=fanhua_history&p=65
                    [menu_order] => 0
                    [post_type] => fanhua_history
                    [post_mime_type] =>
                    [comment_count] => 0
                    [filter] => raw
                )

            [6] => WP_Post Object
                (
                    [ID] => 66
                    [post_author] => 1
                    [post_date] => 2025-02-27 10:05:56
                    [post_date_gmt] => 2025-02-27 02:05:56
                    [post_content] =>
                    [post_title] => 胡歌捐缝纫机给繁花剧组
                    [post_excerpt] =>
                    [post_status] => publish
                    [comment_status] => closed
                    [ping_status] => closed
                    [post_password] =>
                    [post_name] => 66
                    [to_ping] =>
                    [pinged] =>
                    [post_modified] => 2025-02-27 10:06:11
                    [post_modified_gmt] => 2025-02-27 02:06:11
                    [post_content_filtered] =>
                    [post_parent] => 0
                    [guid] => https://example3.chenzhuzhen.cn/?post_type=fanhua_history&p=66
                    [menu_order] => 0
                    [post_type] => fanhua_history
                    [post_mime_type] =>
                    [comment_count] => 0
                    [filter] => raw
                )

        )
    [post_count] => 7
    [current_post] => -1
    [before_loop] => 1
    [in_the_loop] =>
    [post] => WP_Post Object
        (
            [ID] => 74
            [post_author] => 1
            [post_date] => 2025-02-27 16:17:12
            [post_date_gmt] => 2025-02-27 08:17:12
            [post_content] =>
            [post_title] => X先生的打字机
            [post_excerpt] =>
            [post_status] => publish
            [comment_status] => closed
            [ping_status] => closed
            [post_password] =>
            [post_name] => x%e5%85%88%e7%94%9f%e7%9a%84%e6%89%93%e5%ad%97%e6%9c%ba
            [to_ping] =>
            [pinged] =>
            [post_modified] => 2025-02-27 16:17:12
            [post_modified_gmt] => 2025-02-27 08:17:12
            [post_content_filtered] =>
            [post_parent] => 0
            [guid] => https://example3.chenzhuzhen.cn/?post_type=fanhua_history&p=74
            [menu_order] => 0
            [post_type] => fanhua_history
            [post_mime_type] =>
            [comment_count] => 0
            [filter] => raw
        )
    [comment_count] => 0
    [current_comment] => -1
    [found_posts] => 7
    [max_num_pages] => 0
    [max_num_comment_pages] => 0
    [is_single] =>
    [is_preview] =>
    [is_page] =>
    [is_archive] =>
    [is_date] =>
    [is_year] =>
    [is_month] =>
    [is_day] =>
    [is_time] =>
    [is_author] =>
    [is_category] =>
    [is_tag] =>
    [is_tax] =>
    [is_search] =>
    [is_feed] =>
    [is_comment_feed] =>
    [is_trackback] =>
    [is_home] => 1
    [is_privacy_policy] =>
    [is_404] =>
    [is_embed] =>
    [is_paged] =>
    [is_admin] =>
    [is_attachment] =>
    [is_singular] =>
    [is_robots] =>
    [is_favicon] =>
    [is_posts_page] =>
    [is_post_type_archive] =>
    [query_vars_hash:WP_Query:private] => 2f489cdc43f68566e67c65fc2fb2ac65
    [query_vars_changed:WP_Query:private] =>
    [thumbnails_cached] =>
    [allow_query_attachment_by_filename:protected] =>
    [stopwords:WP_Query:private] =>
    [compat_fields:WP_Query:private] => Array
        (
            [0] => query_vars_hash
            [1] => query_vars_changed
        )

    [compat_methods:WP_Query:private] => Array
        (
            [0] => init_query_flags
            [1] => parse_tax_query
        )
)

	

可见$query = new WP_Query($args);经过数据库执行后,其结果都缓存在$query对象里。后面均是围绕上面内容循环遍历文章。

◆ 遍历文章

public function have_posts() {
    if ( $this->current_post + 1 < $this->post_count ) {
        return true;
    } elseif ( $this->current_post + 1 == $this->post_count && $this->post_count > 0 ) {
        do_action_ref_array( 'loop_end', array( &$this ) );
        // Do some cleaning up after the loop.
        $this->rewind_posts();
    } elseif ( 0 === $this->post_count ) {
        $this->before_loop = false;

        do_action( 'loop_no_results', $this );
    }

    $this->in_the_loop = false;
    return false;
}

如上代码,have_posts() 方法通过$this->current_post + 1【这些current_post 、post_count 等变量均来自$query = new WP_Query($args)的查询结果】,比较当前处理的文章索引和文章总数,判断是否还有未处理的文章,并根据不同情况触发相应的动作钩子和进行状态重置。所以,通常会结合 while 循环来遍历查询结果集中的文章。

◆ 获取当前文章内容

public function the_post() {
    global $post;

    if ( ! $this->in_the_loop ) {
        // Only prime the post cache for queries limited to the ID field.
        $post_ids = array_filter( $this->posts, 'is_numeric' );
        // Exclude any falsey values, such as 0.
        $post_ids = array_filter( $post_ids );
        if ( $post_ids ) {
            _prime_post_caches( $post_ids, $this->query_vars['update_post_term_cache'], $this->query_vars['update_post_meta_cache'] );
        }
        $post_objects = array_map( 'get_post', $this->posts );
        update_post_author_caches( $post_objects );
    }
    $this->in_the_loop = true;
    $this->before_loop = false;
    if ( -1 == $this->current_post ) { // Loop has just started.
        do_action_ref_array( 'loop_start', array( &$this ) );
    }

    $post = $this->next_post();
    $this->setup_postdata( $post );
}

public function next_post() {
    ++$this->current_post;
    /** @var WP_Post */
    $this->post = $this->posts[ $this->current_post ];
    return $this->post;
}

如上代码,the_post() 方法作用是将查询结果集中的下一篇文章设置为当前文章,并为该文章设置好相关的数据和上下文,以便后续使用 WordPress 的模板标签(如 the_title()the_content() 等)来显示文章的内容。

其中 next_post() 方法中++$this->current_post 会先将 $this->current_post 的值加 1,然后再使用这个新值。即调用该方法时,current_post 变量值加一,指向下一篇文章。

◆ 恢复主查询的当前文章对象

function wp_reset_postdata() {
    global $wp_query;

    if ( isset( $wp_query ) ) {
        $wp_query->reset_postdata();
    }
}

public function reset_postdata() {
    if ( ! empty( $this->post ) ) {
        $GLOBALS['post'] = $this->post;
        $this->setup_postdata( $this->post );
    }
}

由于new WP_Query()创建的自定义查询,遍历循环时,调用 the_post() 会修改全局 $post 对象。因此如果不重置,后续模板标签(如 the_title())可能继续使用自定义查询的最后一篇文章数据,导致【主查询】或其它地方显示异常,这涉及到主循环等相关概念。

【主查询】:著查询是 WordPress 根据当前访问的 URL 自动生成的默认查询(如:访问首页时,主查询是按时间倒序显示文章列表),存在全局变量$wp_query 中(即WP_Query  对象实例),可通过 global $wp_query进行访问。

【自定义查询】:当创建自定义查询时,$query = new WP_Query($args),即创建一个新的WP_Query实例时,务必使用自定义变量名$query保存数据结果,以避免覆盖保存原本著查询结果的全局变量名$wp_query。这样使用独立的变量名$query创建自定义查询,即$query 是一个独立的新的 WP_Query 对象,其操作不会影响主查询对象 $wp_query

但是$post 是一个全局变量(WP_Post 对象),当在循环中调用 the_post(),会将 $post 设置为循环中的当前文章。所以遍历循环完后,一定要将全局 $post 重置为 存储著查询结果的$wp_query->posts 数组中对应的文章对象。

【主循环重置流程】:如上代码,wp_reset_postdata() 的核心作用是 将 $post 重新指向主查询当前循环的文章。具体过程为主查询($wp_query)保存了循环的进度,其内部有一个变量current_post,记录当前循环到了第几篇文章(例如首页文章列表中的第3篇文章)。调用 wp_reset_postdata() 时,将全局 $post 设置为 $wp_query->posts 数组中对应的文章对象。

所以,了解以上机理。当你使用自定义查询时,其返回结果,如果你用原本保存著查询结果的全局变量$wp_query,即$wp_query = new WP_Query($args);这会造成严重后果,原始主查询(如页面内容、文章详情等)被彻底替换,就算用wp_reset_postdata() 只能恢复被覆盖后的 $wp_query 的状态。所以,再次强调:永远不要直接覆盖 $wp_query:它是 WordPress 的核心全局变量,存储主查询数据。正确做法应使用独立的变量名(如 $query)创建自定义查询。