WP DEVELOP

EP030. “首页拉取 Event、建立 single-event.php 与 archive-event.php”

首页 WordPress 开发课程 CUSTOM POST TYPE 入门 · EP030
约 24 分钟· #EP030#CUSTOM POST TYPE 入门
🔒 登录后可标记已读

上一讲注册好了 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_archiverewrite

代码实现


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_QueryWP 内建 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_archiveregister_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