PHP 架构
OOP、Composer 与资源。
WordPress 里的 PHP 实战
这一课你将能做到
- 在模板里正确驱动主循环(The Loop),并说清它与主查询($wp_query)的关系
- 用 pre_get_posts 改主查询、用 WP_Query 开次级查询,且知道何时必须 wp_reset_postdata()
- 写出 WP 风格的 PHP 8.2 代码:Yoda 条件、命名空间、late escaping(输出时转义)
为什么要学
WP 本质是一个 PHP 应用。你学的 PHP 8.2 特性(只读属性、枚举、命名空间)在 WP 里全部可用,但 WP 有自己的「方言」:全局变量、The Loop、条件标签、转义函数家族。摸清这套方言,模板和插件才不会互相污染数据。
人话:The Loop 相当于一个游标。WP 根据 URL 先生成一次「主查询」存进全局 $wp_query,模板里 have_posts()/the_post() 就是推动游标逐条输出。你中途另开一个 WP_Query 查询会把「当前文章」这个全局指针挪走——不归位,后面的循环全部错乱,这是新手最高频的事故。
先建立图像
URL: /category/java/
↓ rewrite 解析 → 主查询 WP_Query( category_name=java ) 存入 $wp_query
↓ 模板层级选中 category.php
category.php:
have_posts()? ──yes→ the_post() → $post 指向当前行 → the_title()/the_content()
↑ ↓
└────────── while 循环直到 false ←──────┘
↓
wp_reset_postdata()(次级查询后必须调)
跟着做
步骤 1:标准主循环
在子主题 single.php 中:
<?php
get_header();
if ( have_posts() ) :
while ( have_posts() ) :
the_post();
?>
<article>
<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
<time><?php echo esc_html( get_the_date( 'Y-m-d' ) ); ?></time>
<div class="content"><?php the_content(); ?></div>
</article>
<?php
endwhile;
else :
echo '<p>暂无内容</p>';
endif;
get_footer();
the_*() 系列直接输出(内部 echo),get_the_*() 返回值——需要转义、拼接时用后者。
步骤 2:条件标签分流
if ( is_front_page() ) {
get_template_part( 'template-parts/hero', 'home' );
} elseif ( is_single() ) {
get_template_part( 'template-parts/card', get_post_type() );
} elseif ( is_category( 'java' ) ) {
echo '<div class="badge">Java 专栏</div>';
} elseif ( is_page( 'about' ) ) {
get_template_part( 'template-parts/team' );
}
常用族:is_single/is_page/is_archive/is_category/is_tag/is_search/is_404/is_admin/is_paged。
步骤 3:改主查询的正确入口
需求:分类页每页显示 6 篇并排除置顶。不要在模板里写 query_posts(),挂 pre_get_posts:
add_action( 'pre_get_posts', function ( WP_Query $query ): void {
if ( is_admin() || ! $query->is_main_query() ) {
return; // 只动前台主查询
}
if ( $query->is_category() ) {
$query->set( 'posts_per_page', 6 );
$query->set( 'ignore_sticky_posts', true );
}
} );