EP044. “用 ACF 字段让页面横幅(Page Banner)动态化”
🔒 登录后可标记已读页面顶部的 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 规则(
== postOR!= 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