自定义WP短代码显示正常但更新页面时返回无效JSON响应错误
短代码引发Gutenberg更新失败:“响应不是有效的JSON响应”的原因及修复
问题描述
我创建了一个用于展示特定CPT(自定义文章类型)循环的自定义短代码,代码如下:
function bundle_grid_shortcode() { $args = array( 'post_type' => 'bundle', 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', ); $query = new WP_Query( $args ); echo '<div class="container">'; echo '<div class="row text-center justify-content-center">'; if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); $steam = get_field('steam'); $nx = get_field('nintendo'); $t1 = get_field('title1'); $t2 = get_field('title2'); $percentage = get_field('percentage'); $setdate = get_field('date'); ?> <div class="col-lg-4 col-xs-12"> <div id="post-<?php the_ID(); ?>" class="card card-bundle"> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"> <?php if ( has_post_thumbnail() ) { the_post_thumbnail(); } else { echo '<img src="https://picsum.photos/seed/picsum/1920/1080" class="img-responsive img-fluid card-img-top" alt="dummy img" />'; } ?> </a> <div class="card-body"> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"> <?php the_title(); ?> </a> </div> </div> </div> <?php } } echo '</div></div>'; wp_reset_postdata(); } add_shortcode('bundle-grid', 'bundle_grid_shortcode');
该短代码在前端可正常显示所需内容,但通过Gutenberg编辑器更新页面时,会弹出提示‘更新失败。响应不是有效的JSON响应’,请问这是什么原因?
原因分析
核心问题出在短代码的输出方式上:
- Gutenberg编辑器通过REST API处理页面保存请求,要求服务器返回标准JSON格式的响应。
- 你的短代码直接使用
echo输出HTML内容,这些内容会在REST API请求执行过程中被提前输出,混入原本应该是纯JSON的响应体中,导致响应格式失效,触发错误。 - 前端显示正常是因为前端渲染时,短代码的输出是直接注入页面HTML,不需要符合JSON格式要求。
解决方案
修改短代码,将所有HTML内容收集到变量中,最后返回变量内容,而非直接echo输出——这是WordPress短代码的规范写法。
修改后的代码如下:
function bundle_grid_shortcode() { $args = array( 'post_type' => 'bundle', 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', ); $query = new WP_Query( $args ); // 初始化内容变量 $output = '<div class="container">'; $output .= '<div class="row text-center justify-content-center">'; if ( $query->have_posts() ) { ob_start(); // 开启输出缓冲,捕获PHP模板输出的内容 while ( $query->have_posts() ) { $query->the_post(); $steam = get_field('steam'); $nx = get_field('nintendo'); $t1 = get_field('title1'); $t2 = get_field('title2'); $percentage = get_field('percentage'); $setdate = get_field('date'); ?> <div class="col-lg-4 col-xs-12"> <div id="post-<?php the_ID(); ?>" class="card card-bundle"> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"> <?php if ( has_post_thumbnail() ) { the_post_thumbnail(); } else { echo '<img src="https://picsum.photos/seed/picsum/1920/1080" class="img-responsive img-fluid card-img-top" alt="dummy img" />'; } ?> </a> <div class="card-body"> <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"> <?php the_title(); ?> </a> </div> </div> </div> <?php } // 获取缓冲的内容并追加到output变量 $output .= ob_get_clean(); } $output .= '</div></div>'; wp_reset_postdata(); // 返回内容而非直接输出 return $output; } add_shortcode('bundle-grid', 'bundle_grid_shortcode');
关键修改点:
- 用
$output变量收集静态HTML内容,替代直接echo。 - 对于PHP模板片段(
?> ... <?php之间的内容),使用ob_start()和ob_get_clean()开启并捕获输出缓冲,避免内容直接流入响应流。 - 最后通过
return $output返回所有内容,符合WordPress短代码的规范要求。
内容的提问来源于stack exchange,提问作者Julia Galden
相关产品推荐
相关产品推荐

