EP030. “首页拉取 Event、建立 single-event.php 与 archive-event.php”
🔒 登录后可标记已读上一讲注册好了 event 文章类型,这一讲开始把它真正用起来:在首页用 WP_Query 写一个新的自定义查询,把「Upcoming Events」区块的假 HTML 换成两条真实的 event 文章;点击进去要有专属的单篇模板(而不是借用博客的 single.php);点「View All Events」要能进到一个专属的归档模板(而不是借用 archive.php)。过程中会踩到两个「明明代码没错却看到 Page Not Found」的坑:一个是永久链接(permalink)结构没重建,一个是文章类型没开 has_archive。
涉及文件
wp-content/themes/fictional-university-theme/front-page.php(修改,新增 Upcoming Events 的自定义查询)wp-content/themes/fictional-university-theme/single-event.php(新建,以single.php为起点改)wp-content/themes/fictional-university-theme/archive-event.php(新建,以archive.php为起点改)wp-content/mu-plugins/university-post-types.php(修改,加has_archive和rewrite)
代码实现
1. front-page.php ——「Upcoming Events」区块从假数据换成真查询
// wp-content/themes/fictional-university-theme/front-page.php
// 「Upcoming Events」标题下方,这一块是新增的自定义查询(原本是两张写死的 event-summary div)
<?php
$homepageEvents = new WP_Query(array(
'posts_per_page' => 2,
'post_type' => 'event'
));
while($homepageEvents->have_posts()) {
$homepageEvents->the_post(); ?>
<div class="event-summary">
<a class="event-summary__date t-center" href="#">
<span class="event-summary__month">Mar</span>
<span class="event-summary__day">25</span>
</a>
<div class="event-summary__content">
<h5 class="event-summary__title headline headline--tiny"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h5>
<p><?php echo wp_trim_words(get_the_content(), 18); ?> <a href="<?php the_permalink(); ?>" class="nu gray">Learn more</a></p>
</div>
</div>
<?php }
?>
<p class="t-center no-margin"><a href="#" class="btn btn--blue">View All Events</a></p>
要点:
- 跟 EP026 的博客查询一样,用
new WP_Query(array(...))自建查询对象,循环时要用$homepageEvents->have_posts()/$homepageEvents->the_post(),不能用裸的have_posts()。 - 关键新参数是
post_type => 'event',告诉 WordPress 只从 event 这个文章类型里查。 - 日期圈(月/日)这一讲还没接真数据,仍是写死的
Mar/25,标题和摘要链接的href也还没指向get_the_permalink()对应的正确目标之外的东西——本讲只是先把标题、摘要、permalink 接上真数据。 - 「View All Events」按钮的
href这一讲还是占位符#,留到 EP031 才接上get_post_type_archive_link()。
[截图:前台首页"Upcoming Events"区块,标题和摘要已换成真实 event 文章数据的画面]
2. single-event.php(新建)
WordPress 会自动按 single-{post_type}.php 的命名规则去找对应文章类型的单篇模板,所以只要建一个叫 single-event.php 的文件,event 文章的详情页就会自动改用它。以 single.php 复制过来后做了两处调整:去掉了「作者/日期/分类」的博客风格 meta 信息,改成直接显示标题;「Blog Home」链接改成「Events Home」,并且用 get_post_type_archive_link('event') 动态生成归档链接(而不是写死 URL,这样以后改 slug 也不用回来改这里)。
// wp-content/themes/fictional-university-theme/single-event.php
<?php
get_header();
while(have_posts()) {
the_post(); ?>
<div class="page-banner">
<div class="page-banner__bg-image" style="background-image: url(<?php echo get_theme_file_uri('/images/ocean.jpg') ?>);"></div>
<div class="page-banner__content container container--narrow">
<h1 class="page-banner__title"><?php the_title(); ?></h1>
<div class="page-banner__intro">
<p>DONT FORGET TO REPLACE ME LATER</p>
</div>
</div>
</div>
<div class="container container--narrow page-section">
<div class="metabox metabox--position-up metabox--with-home-link">
<p><a class="metabox__blog-home-link" href="<?php echo get_post_type_archive_link('event'); ?>"><i class="fa fa-home" aria-hidden="true"></i> Events Home</a> <span class="metabox__main"><?php the_title(); ?></span></p>
</div>
<div class="generic-content"><?php the_content(); ?></div>
</div>
<?php }
get_footer();
?>
3. archive-event.php(新建)
同理,WordPress 会自动按 archive-{post_type}.php 命名规则找归档模板。以 archive.php 为起点,把标题/副标题改成写死的「All Events」文案,循环内容换成跟首页一样的 event-summary 卡片结构(日期圈这一讲仍是写死的):
// wp-content/themes/fictional-university-theme/archive-event.php
<?php
get_header(); ?>
<div class="page-banner">
<div class="page-banner__bg-image" style="background-image: url(<?php echo get_theme_file_uri('/images/ocean.jpg') ?>);"></div>
<div class="page-banner__content container container--narrow">
<h1 class="page-banner__title">All Events</h1>
<div class="page-banner__intro">
<p>See what is going on in our world.</p>
</div>
</div>
</div>
<div class="container container--narrow page-section">
<?php
while(have_posts()) {
the_post(); ?>
<div class="event-summary">
<a class="event-summary__date t-center" href="#">
<span class="event-summary__month">Mar</span>
<span class="event-summary__day">25</span>
</a>
<div class="event-summary__content">
<h5 class="event-summary__title headline headline--tiny"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h5>
<p><?php echo wp_trim_words(get_the_content(), 18); ?> <a href="<?php the_permalink(); ?>" class="nu gray">Learn more</a></p>
</div>
</div>
<?php }
echo paginate_links();
?>
</div>
<?php get_footer();
?>
注意这个归档模板直接用的是 WordPress 默认 URL 查询(裸的 have_posts()/the_post()),不是自定义 WP_Query,因为归档页本来就该用 WordPress 自己按 URL 生成的默认查询。
[截图:前台 /events 归档页"All Events",列出所有活动卡片的画面]
4. mu-plugins/university-post-types.php —— 加 has_archive 和 rewrite slug
// wp-content/mu-plugins/university-post-types.php
function university_post_types() {
register_post_type('event', array(
'rewrite' => array('slug' => 'events'), // 新增:让归档/单篇 URL 用复数 events 作为 slug
'has_archive' => true, // 新增:让 event 拥有归档页(不然 /events 会 404)
'public' => true,
'show_in_rest' => true,
'labels' => array(
'name' => 'Events',
'add_new_item' => 'Add New Event',
'edit_item' => 'Edit Event',
'all_items' => 'All Events',
'singular_name' => 'Event'
),
'menu_icon' => 'dashicons-calendar'
));
}
add_action('init', 'university_post_types');
Hook / Function 速查
| 名称 | 类型 | 用途 |
|---|---|---|
WP_Query | WP 内建 class | 自定义查询,本讲用来指定 post_type => 'event' |
get_post_type_archive_link($post_type) | WP 内建 function(返回值,需 echo) | 动态生成某个文章类型的归档页 URL,比写死 URL 更保险 |
single-{post_type}.php | 主题模板命名约定 | WordPress 自动用这个命名规则匹配某文章类型的单篇模板,本讲对应 single-event.php |
archive-{post_type}.php | 主题模板命名约定 | 同理,自动匹配某文章类型的归档模板,本讲对应 archive-event.php |
has_archive | register_post_type() 参数 | 设为 true 才会有归档 URL(如 /events),否则访问会 404 |
rewrite => array('slug' => ...) | register_post_type() 参数 | 自定义该文章类型 URL 里用的 slug 关键字(这里让单数注册名 event 对应复数 URL events) |
常见坑
- 注册好新文章类型、点进单篇后地址栏是
/event/xxx,但页面显示 "Page Not Found" 且是博客模板:这不是代码错,而是 WordPress 的永久链接结构还没重建。需要去 设置 → 固定链接(Permalinks)随便点一下「保存更改」,让 WordPress 重新识别event这个新关键字。WordPress 不会在每次保存代码时都自动重建永久链接结构,出于性能考虑只在关键时刻才重建。 - 访问
/event(归档页)显示空白 + Page Not Found:因为注册文章类型时没告诉 WordPress 这个类型需要归档页,要加has_archive => true。 - 加了
rewrite slug改成events(复数)后,旧的/event地址会立刻失效变成 404,这是预期行为,不是 bug。
延伸 / 后续讲座会用到
EP031 会给 event 加 excerpt 支持、修好「View All Events」按钮和头部导航的 Events 高亮。EP032 会引入 ACF 插件,把日期圈从写死的 Mar 25 换成真正可编辑的日期字段。
Sources
Udemy:
- Become a WordPress Developer: Unlocking Power With Code — Section 7, EP030