WP DEVELOP

EP209. “搭建 single/page/blogindex 三个模板与 front-page 拆分”

首页 WordPress 开发课程 BLOCK THEME(2024 最佳实践) · EP209
约 23 分钟· #EP209#BLOCK THEME(2024 最佳实践)
🔒 登录后可标记已读

用 EP199-200 建立的 PlaceholderBlock 套路,批量搭建剩下几个最常用的模板:单篇文章(singlepost)、单个页面(page)、博文列表(blogindex)——每一个都是「新建占位 Block + 直接从传统主题对应文件搬运既有 PHP」,模式高度重复,一次性讲透之后后面的模板会很快。同时理清楚 index.htmlfront-page.html 的分工index.html 是「博文列表」这个 URL 该用的模板(因为 front-page.html 不存在时,WordPress 会退回用 index.html 当首页),一旦故意新建了专门的 front-page.html(用来当真正的自定义首页),index.html 就该改造成博文列表专用;这跟 WordPress 后台「设置 → 阅读」里「首页显示:静态页面」这个选项配合使用,才能让首页和博文列表各自独立、互不冲突。


涉及文件

  • wp-content/themes/fictional-university-block-theme/functions.php (修改,新增 3 个 PlaceholderBlock 实例)
  • wp-content/themes/fictional-university-block-theme/our-blocks/singlepost.js / singlepost.php (新建)
  • wp-content/themes/fictional-university-block-theme/our-blocks/page.js / page.php (新建)
  • wp-content/themes/fictional-university-block-theme/our-blocks/blogindex.js / blogindex.php (新建)
  • wp-content/themes/fictional-university-block-theme/templates/single.html (修改)
  • wp-content/themes/fictional-university-block-theme/templates/page.html (新建)
  • wp-content/themes/fictional-university-block-theme/templates/front-page.html (新建,原 index.html 的完整首页内容搬到这里)
  • wp-content/themes/fictional-university-block-theme/templates/index.html (修改,改造成博文列表专用)

代码实现

functions.php:批量新增三个占位 Block

new PlaceholderBlock("eventsandblogs");
new PlaceholderBlock("header");
new PlaceholderBlock("footer");
new PlaceholderBlock("singlepost");
new PlaceholderBlock("page");
new PlaceholderBlock("blogindex");

our-blocks/singlepost.php(新建,原样搬运传统主题 single.php 里 while 循环内部的正文部分——按 EP208 的规则,单篇内容不再需要 while 循环)

<?php

    pageBanner();
     ?>

    <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 site_url('/blog'); ?>"><i class="fa fa-home" aria-hidden="true"></i> Blog Home</a> <span class="metabox__main">Posted by <?php the_author_posts_link(); ?> on <?php the_time('n.j.y'); ?> in <?php echo get_the_category_list(', '); ?></span></p>
      </div>

      <div class="generic-content"><?php the_content(); ?></div>

    </div>

our-blocks/page.php(新建,原样搬运传统主题 page.php,同样不需要 while 循环)

<?php

    pageBanner();
     ?>

    <div class="container container--narrow page-section">
    
    <?php
      $theParent = wp_get_post_parent_id(get_the_ID());
      if ($theParent) { ?>
        <div class="metabox metabox--position-up metabox--with-home-link">
      <p><a class="metabox__blog-home-link" href="<?php echo get_permalink($theParent); ?>"><i class="fa fa-home" aria-hidden="true"></i> Back to <?php echo get_the_title($theParent); ?></a> <span class="metabox__main"><?php the_title(); ?></span></p>
    </div>
      <?php }
    ?>

    <?php 
    $testArray = get_pages(array(
      'child_of' => get_the_ID()
    ));

    if ($theParent or $testArray) { ?>
    <div class="page-links">
      <h2 class="page-links__title"><a href="<?php echo get_permalink($theParent); ?>"><?php echo get_the_title($theParent); ?></a></h2>
      <ul class="min-list">
        <?php
          if ($theParent) {
            $findChildrenOf = $theParent;
          } else {
            $findChildrenOf = get_the_ID();
          }

          wp_list_pages(array(
            'title_li' => NULL,
            'child_of' => $findChildrenOf,
            'sort_column' => 'menu_order'
          ));
        ?>
      </ul>
    </div>
    <?php } ?>

    <div class="generic-content">
      <?php the_content(); ?>
    </div>

  </div>

our-blocks/blogindex.php(新建,原样搬运传统主题 index.php——这是列表页,依然保留 while 循环)

<?php 

pageBanner(array(
  'title' => 'Welcome to our blog!',
  'subtitle' => 'Keep up with our latest news.'
));
 ?>
<div class="container container--narrow page-section">
<?php
  while(have_posts()) {
    the_post(); ?>
    <div class="post-item">
      <h2 class="headline headline--medium headline--post-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
      
      <div class="metabox">
        <p>Posted by <?php the_author_posts_link(); ?> on <?php the_time('n.j.y'); ?> in <?php echo get_the_category_list(', '); ?></p>
      </div>

      <div class="generic-content">
        <?php the_excerpt(); ?>
        <p><a class="btn btn--blue" href="<?php the_permalink(); ?>">Continue reading &raquo;</a></p>
      </div>

    </div>
  <?php }
  echo paginate_links();
?>
</div>

templates/single.html / templates/page.html:都是「页头 + 对应内容占位 Block + 页脚」三段式

<!-- wp:ourblocktheme/header /-->

<!-- wp:ourblocktheme/singlepost /-->

<!-- wp:ourblocktheme/footer /-->
<!-- wp:ourblocktheme/header /-->

<!-- wp:ourblocktheme/page /-->

<!-- wp:ourblocktheme/footer /-->

templates/front-page.html:把原本 index.html 里完整的首页布局(Banner/事件博文/幻灯片等)原样搬过来(内容跟 EP205-207 写定的 index.html 完全一致,此处不重复贴)

templates/index.html:改造成博文列表专用,三段式换成 blogindex

<!-- wp:ourblocktheme/header /-->

<!-- wp:ourblocktheme/blogindex /-->

<!-- wp:ourblocktheme/footer /-->

关键改动点:

  • 每个模板的搭建套路完全一致,只是内容不同:① functions.php 加一行 new PlaceholderBlock("块名");② 复制一份已有的最简单 JS 文件(比如 header.js),只改 Block 名字/标题/占位文字;③ 新建对应的 PHP 文件,从传统主题里找到对应的旧模板文件,把「不需要的头尾」(页头/页脚,已经由独立的 header/footer Block 负责)删掉,只留中间的动态内容部分,粘贴过来
  • singlepost/page 两个「单篇」类型的 Block,不需要 while 循环:直接复制传统主题 single.php/page.php 里原本 while 循环内部的代码,跳过外层循环——这是 EP208 讲过的 WordPress 6.4 新规则的直接应用
  • blogindex(博文列表)依然需要 while 循环:因为这是「同时显示多篇文章」的场景,不属于 EP208 规则覆盖的「单篇」情形,循环逻辑原样保留
  • page.php 复用了传统主题已经写好的「面包屑导航 + 子页面列表」逻辑wp_get_post_parent_id() 判断当前页面是否有上级页面(决定要不要显示「返回上级」链接)、get_pages() 查询当前页面的所有子页面(决定要不要显示子页面链接列表)——这些细节都是传统主题章节早就写好验证过的代码,原样复制,不需要为了适配 Block Theme 重新设计
  • front-page.htmlindex.html 的分工
    • 在 WordPress 里,如果专门存在一个 front-page.html(或 front-page.php)模板文件,只要网站首页设置成「显示一个静态页面」(在「设置 → 阅读」里选择,这门课传统主题章节已经配置过:Home 页面当首页,Blog 页面当博文列表),访问首页 URL 就会优先使用这个模板
    • index.html兜底模板——理论上任何没有更具体匹配模板的请求最终都会退到它;这门课的用法是让它专门服务「博文列表」这个 URL(因为「Blog」这个页面本身是空的,只是为了占一个 URL slug,真正的列表内容渲染逻辑就落在 index.html 身上)
    • 操作步骤:把原本写在 index.html 里的完整首页布局(页头/Banner/事件博文/幻灯片/页脚)整个搬到新建的 front-page.htmlindex.html 精简成「页头 + blogindex + 页脚」三段
  • 改完模板文件记得清除编辑器里的自定义项:因为之前对 index.html 的编辑记录存在数据库里,文件改了之后如果不去「模板」列表点「清除自定义项」,页面依然会显示数据库里存的旧版本内容,容易造成「明明改了文件却没生效」的困惑——这一讲再次踩到这个坑,也再次印证了这个机制的重要性

Hook / Function 速查

名称类型用途
templates/front-page.htmlBlock Theme 模板文件网站设置为「显示静态页面」时,首页 URL 优先匹配的模板
templates/index.htmlBlock Theme 模板文件兜底模板,这里专门用来承载博文列表内容
wp_get_post_parent_id($ID)WP 内建 function获取指定页面的上级页面 ID,用于判断是否显示面包屑
get_pages(array('child_of' => $ID))WP 内建 function查询指定页面的所有子页面

常见坑

  • 「单篇」类型的模板(singlepost.php/page.php)继续保留 while 循环——按 EP208 的规则会导致内容空白/报错
  • 「列表」类型的模板(blogindex.php)误删了 while 循环——只会显示不完整的内容甚至报错,因为这类场景确实需要遍历多篇文章
  • 只建了 front-page.html,忘记同步把 index.html 从完整首页布局改造成博文列表专用——会导致首页和博文列表显示同样的内容
  • 改完模板文件后没有去后台「模板」列表清除自定义项——页面继续显示数据库里存的旧版本,看起来像是改动没生效

[截图:前台 /blog 博文列表页正确渲染出文章标题/摘要/分页,而首页依然显示完整的 Banner+幻灯片布局,两者互不冲突]


延伸 / 后续讲座会用到

下一讲继续搭建剩余的模板(自定义文章类型详情页、归档页等),套路跟这一讲完全一致,会进展得更快。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 28, EP209