研究循环文章的the_post()功能,发现全局变量 $post 已经存储了文章数据,最后还需要执行一个函数
$this->setup_postdata( $post );
把文章数据接着转换为更具体地全局变量
public function setup_postdata( $post ) {
global $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages;
...
$id = $elements['id'];
$authordata = $elements['authordata'];
$currentday = $elements['currentday'];
$currentmonth = $elements['currentmonth'];
$page = $elements['page'];
$pages = $elements['pages'];
$multipage = $elements['multipage'];
$more = $elements['more'];
$numpages = $elements['numpages'];
为何要这么操作呢?带着疑问,查找相关资料,汇总如下:
$post 变量的局限性
虽然 $post 是全局变量,但它仅包含文章本身的基本属性(如 post_title、post_content)。而 WordPress 的模板系统依赖更多全局变量来提供便捷访问:
- $id:当前文章 ID(用于简化访问,避免每次写 $post->ID)。
- $authordata:文章作者的用户对象(包含头像、昵称等扩展信息)。
- $currentday/$currentmonth:文章发布日期的格式化信息。
- $page/$pages/$multipage:用于处理文章分页的变量。
例如,在模板文件中,你可以直接使用这些变量:
// 无需 $post->ID,直接使用 $id
echo "当前文章 ID: $id";
// 直接访问作者对象
echo "作者头像: " . get_avatar( $authordata->ID );
setup_postdata()
的核心功能
- 填充全局变量
function setup_postdata( $post ) {
global $id, $authordata, $currentday, $currentmonth, $page, $pages, $multipage, $more, $numpages;
$id = $post->ID;
$authordata = get_userdata( $post->post_author );
$currentday = mysql2date( 'd', $post->post_date );
$currentmonth = mysql2date( 'm', $post->post_date );
// ...其他变量设置...
}
这些变量在模板文件(如 single.php
、loop.php
)中广泛使用,是 WordPress 模板系统的基础。
- 触发钩子机制
do_action_ref_array( 'the_post', array( &$post, &$this ) );
the_post
钩子允许插件在文章数据设置后立即介入,修改或扩展文章对象。例如:
add_action( 'the_post', 'add_custom_data_to_post' );
function add_custom_data_to_post( &$post ) {
$post->custom_field = get_post_meta( $post->ID, 'custom_field', true );
}
这样,在模板中可以直接访问 $post->custom_field
。如果绕过 setup_postdata(),插件将无法正常工作。
- 维护文章上下文
setup_postdata() 还会更新其他全局状态,如:
$wp_query->in_the_loop:标记当前是否在主循环中。
$wp_current_filter:记录当前执行的钩子栈,用于调试。
为什么不直接在 $post
中包含所有数据?
查找相关资料,还了解到:WordPress 早期版本(甚至在引入 WP_Post
对象之前)就依赖这些全局变量。为了保持向后兼容,这些变量被保留下来。
而且,$post 对象专注于存储数据库中的原始文章数据,而全局变量则提供模板渲染所需的辅助信息。这种分离使代码更清晰。