WP DEVELOP

EP044. “用 ACF 字段让页面横幅(Page Banner)动态化”

首页 WordPress 开发课程 PROFESSOR POST TYPE · EP044
约 10 分钟· #EP044#PROFESSOR POST TYPE
🔒 登录后可标记已读

页面顶部的 page banner 区域,标题一直是动态的(the_title()),但副标题和背景图这一讲之前一直是写死的 占位文字「DONT FORGET TO REPLACE ME LATER」和写死的 ocean.jpg。这一讲用 ACF 新建一个「Page Banner」 字段组,包含副标题(文本)和背景图(图片)两个字段,让每一篇内容都能自己上传专属的 banner 背景图和 填写专属副标题。之所以不能像教授头像那样直接用特色图片字段,是因为 professor 的特色图片已经被 头像占用了——WordPress 一篇内容只能有一个特色图片,所以背景图必须另外用一个 ACF 图片字段来存。 这一讲先只在 single-professor.php 里接好这两个字段,其他模板(page.php、single.php 等)这一讲还没改, 留到下一讲统一抽成可复用的 function 再处理。

涉及文件

  • wp-content/themes/fictional-university-theme/functions.php (修改,新增 pageBanner 图片尺寸)
  • wp-content/themes/fictional-university-theme/single-professor.php (修改,page banner 区块改用 ACF 字段)
  • ACF 后台设置(不是代码文件):新建「Page Banner」字段组,两个字段 page_banner_subtitle(文本)、
    page_banner_background_image(图片),Location 规则设置成对所有文章类型都生效

代码实现


ACF 后台:新建 Page Banner 字段组

在 Custom Fields 里新建字段组,命名 Page Banner,加两个字段:

  • page_banner_subtitle,类型保持默认的 Text。
  • page_banner_background_image,类型改成 Image(在 Content 分类底下)。

Location 规则这一讲要覆盖所有文章类型(blog post、page、event、program、professor),但 ACF 界面 没有「全选」选项,讲师用了一个技巧:留着默认的「Post Type == post」规则,再点 OR 按钮加一条 「Post Type != post」。这两条规则用 OR 连接,只要满足其中一条就会显示——而这两条合起来对任何文章类型 永远至少有一条成立,效果等同于「无论什么文章类型都显示」。

[截图:ACF"Page Banner"字段组设置画面,含 page_banner_subtitle 文本字段、page_banner_background_image 图片字段,以及用两条 OR 规则拼出的 Location 设置]


functions.php(修改)

在上一讲已有的两个教授图片尺寸后面,再加一个专门给 banner 背景用的尺寸,很宽但不高:

function university_features() {
  add_theme_support('title-tag');
  add_theme_support('post-thumbnails');
  add_image_size('professorLandscape', 400, 260, true);
  add_image_size('professorPortrait', 480, 650, true);
  add_image_size('pageBanner', 1500, 350, true);
}

single-professor.php(修改)

page banner 区块里,副标题从写死文字改成 the_field() 输出 ACF 字段值:

<p><?php the_field('page_banner_subtitle') ?></p>

背景图从写死的 ocean.jpg 改成 ACF 图片字段。ACF 的图片字段返回的是一个数组,直接用 ['url'] 拿到的是原图(还是太大),所以要用 ['sizes']['pageBanner'] 取出上面新注册的那个裁切尺寸:

<div class="page-banner__bg-image" style="background-image: url(<?php $pageBannerImage = get_field('page_banner_background_image'); echo $pageBannerImage['sizes']['pageBanner'] ?>);"></div>

原文提到一个排查技巧:如果不确定某个 ACF 字段返回的数据结构长什么样(比如这里一开始不知道图片字段 是数组、也不知道数组里有没有 sizes 这个 key),可以先在页面上随便找个位置 print_r($变量名) 把整个 变量结构打印出来看一眼,确认好结构后再把调试代码删掉,正式换成上面这种精确取值的写法。

[截图:前台某位教授详情页顶部 page banner,背景图和副标题已改用 ACF 字段动态显示的画面]

Hook / Function 速查

名称类型用途
the_field($name)ACF function(直接输出)直接输出某个 ACF 字段的值,等价于 echo get_field($name)
get_field($name)ACF function(返回值)取出 ACF 字段的值;图片字段返回一个数组
print_r($var)PHP 内建 function把变量内部结构打印出来,用来排查/确认一个不熟悉的变量(比如 ACF 图片字段)到底长什么样

常见坑

  • ACF 的图片字段(image field)返回的不是一个 URL 字符串,而是一个数组,里面有 url(原图地址)和
    sizes(各个已注册图片尺寸的地址,按尺寸昵称取)。直接当字符串用会出错。
  • 只取 ['url'] 会拿到原图(这里是准备展示在 1500×350 的窄横幅里,原图完全不合适),必须通过
    ['sizes']['对应尺寸昵称'] 才能拿到裁切过的合适尺寸。
  • ACF 后台没有「所有文章类型都生效」这个选项,要用两条互斥的 OR 规则(== post OR != post)拼出
    「永远成立」的效果,这个写法不直观,容易看不懂为什么要这样写。
  • 用 Manual Image Crop 插件裁切新的 banner 背景图之后,跟之前教授头像一样,普通刷新看不到新裁切结果,
    要做一次强制刷新(Shift + 点刷新)才能看到最新版本,这是浏览器缓存导致的,不是插件或 WordPress 的问题。

延伸 / 后续讲座会用到

这一讲的 page banner 逻辑目前只接在 single-professor.php 一个模板里。原文明确提到,如果要让 about us 页面或博客文章也能有自己的 banner 副标题/背景图,理论上要把这段 PHP 复制到 page.php、 single.php 等好几个模板文件里,重复代码太多不划算;下一讲会把这段逻辑抽成一个可复用的 function (调用方式类似 page_banner(array $args)),届时会回来重构掉这一讲写的这段直接内联代码。

Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 9, EP044