PHP 8.0下ACF Pro重复器字段短代码报错修复请求
解决PHP 8.0下ACF Pro重复器短代码的TypeError问题
问题原因
报错str_replace(): Argument #2 ($replace) must be of type string when argument #1 ($search) is a string源于PHP 8.0对函数参数类型的严格检查:当str_replace()第一个参数为字符串时,第二个参数必须是字符串类型。但ACF的get_sub_field()可能返回非字符串值,比如:
- 图片/文件字段返回数组(包含url、id等信息)
- 复选框/开关字段返回布尔值
- 未填充的字段返回
null
这些非字符串值传入str_replace()就会触发TypeError。
修复方案
在获取子字段值后,添加类型转换逻辑,将所有非字符串值转为合适的字符串表示:
修改后的完整代码
/** * ACF Pro repeater field shortcode * * I created this shortcode function because it didn't exist and it was being requested by others * I originally posted it here: https://support.advancedcustomfields.com/forums/topic/repeater-field-shortcode/ * * @attr {string} field - (Required) the name of the field that contains a repeater sub group * @attr {string} sub_fields - (Required) a comma separated list of sub field names that are part of the field repeater group * @attr {string} post_id - (Optional) Specific post ID where your value was entered. Defaults to current post ID (not required). This can also be options / taxonomies / users / etc */ function my_acf_repeater($atts, $content='') { extract(shortcode_atts(array( "field" => null, "sub_fields" => null, "post_id" => null ), $atts)); if (empty($field) || empty($sub_fields)) { return ""; } $sub_fields = explode(",", $sub_fields); $_finalContent = ''; if( have_rows($field, $post_id) ): while ( have_rows($field, $post_id) ) : the_row(); $_tmp = $content; foreach ($sub_fields as $sub) { $subValue = get_sub_field(trim($sub)); // 处理非字符串类型的字段值 if (is_array($subValue)) { // 针对ACF图片/文件字段优先提取url;其他数组转为JSON字符串 $subValue = isset($subValue['url']) ? $subValue['url'] : json_encode($subValue); } elseif (is_bool($subValue)) { // 布尔值转为字符串 $subValue = $subValue ? 'true' : 'false'; } elseif ($subValue === null) { // null转为空字符串 $subValue = ''; } else { // 其他类型强制转为字符串 $subValue = (string) $subValue; } $_tmp = str_replace("%$sub%", $subValue, $_tmp); } $_finalContent .= do_shortcode( $_tmp ); endwhile; endif; return $_finalContent; } add_shortcode("acf_repeater", "my_acf_repeater");
额外说明
- 如果你的子字段有特殊类型(比如关系字段、用户字段),可以在数组判断分支里添加更针对性的处理,比如关系字段提取标题或ID。
extract()函数在PHP 8.0中仍可使用,但从代码规范角度,建议改用直接访问$atts或手动赋值变量,不过这不是导致当前报错的原因。
内容的提问来源于stack exchange,提问作者Thijmen van Doorn
相关产品推荐
相关产品推荐

