MENU

投稿・固定ページへのPHP埋め込み時「返答が正しいJSONレスポンスではありません」が表示されるときの対策

WordPressの投稿・固定ページへPHPを埋め込む方法がいくつかあります。
しかし方法によっては記事の編集時に「更新に失敗しました。返答が正しいJSONレスポンスではありません」と表示され、動作に問題が生じるようです。

起こりうる条件と、回避方法をまとめました。

目次

こんな方に見てもらいたい

以下のような問題が発生している方へ。

  • WordPressの投稿・固定ページにPHPを埋め込んだ時「返答が正しいJSONレスポンスではありません」というエラーが表示される。
  • 埋め込んだPHPの出力が変な場所に表示される。
  • PHPを埋め込んだ後、固定ページ編集画面の動作があやしい。

発生手順

環境(バージョン)

  • WordPress: 6.4.3
  • PHP: 8.2.16
  • テーマ: SWELL 2.9.0
  • プラグイン:  Code Snippets 3.6.2

PHPの埋め込み方法

Code Snippetsプラグインを用いて、functions.php ファイルにショートコードを追加する方法をとりました。

Code Snippetsプラグインをインストール後、Wordpress編集画面の「スニペット」- 「すべてのスニペット」から「新規追加」をクリック。

外部PHPを読み込むためのショートコードを追加します。記載するコードは https://hmjp.net/archive2019/blog/php-in-wp-article/#toc2 を参考にしました。

投稿・固定ページの編集画面から、下記の様に記載して .phpを読み込みます。
「(工事中です。…」の記載の直後にショートコードを追加していますので、「(工事中です。」の下にphpの実行結果が表示されることが期待されます。

起きた現象

1.下書き保存すると「更新に失敗しました。返答が正しいJSONレスポンスではありません」と表示される

2.投稿・固定ページの編集画面へ遷移するとき、一瞬PHPが実行されてしまう

3.ブロックエディタでの順序と異なるところに、埋め込んだPHPの出力が表示されてしまう。
この例ですと、「(工事中です。…」の記載よりも先にphpの実行結果が表示されてしまっています。

解決方法

ob_start()、ob_get_clean() 関数を必ず挿入する

必要があるようです。これを踏まえて、前記した外部PHPを読み込むためのショートコードを以下の様に変更します。require文の直前に ob_start(); を、直後に ob_get_clean(); を記述しています。

function loadExternalPHP($args) {
  extract(shortcode_atts(array('file' => 'nothing.php'), $args));
  ob_start();
  require ABSPATH . "extra/" . "$file";
  return ob_get_clean();
}
add_shortcode( 'loadPHP', 'loadExternalPHP' );

これらの関数は、PHPでの出力バッファリング(Output Buffering)に関連したものです。

  • ob_start()
    • この関数を実行することで出力バッファリングを開始します。つまり、PHPの出力が直ちにブラウザに送信されるのではなく、バッファに保存されます。
  • ob_get_clean()
    • この関数は、現在の出力バッファの内容を取得し、バッファをクリアします。
    • この例では「require ABSPATH . “extra/” . “$file”;」によって外部のPHPファイルが読み込まれ、その出力がバッファされています。当関数によりこれを取得し、ショートコードの呼び出し箇所に挿入されます。

以上より、loadExternalPHP() 関数の実行終了後に上記require文の出力がブラウザに送信されることになります。これが動作の違いにつながっていると思われます。

修正後の動作

ブロックエディタでの順序通りにPHPの出力が表示されます。
この例では、期待通り「(工事中です。」の下にフォームが表示されていることがわかります。

その他前記した不具合も解消しました。

2024/3 追記:ショートコードの記載は require_once にした方がよいかも

先ほど紹介した例ですと、埋め込むPHPファイルの記載によっては「PHP Fatal error: Cannot redeclare」エラーとなり編集画面に入れないことがありました。

以下の様に「require_once」や「include_once」を使用したほうがよいかもしれません。

function loadExternalPHP($args) {
  extract(shortcode_atts(array('file' => 'nothing.php'), $args));
  ob_start();
  require_once ABSPATH . "extra/" . "$file";
  return ob_get_clean();
}
add_shortcode( 'loadPHP', 'loadExternalPHP' );

参考URL

https://hmjp.net/archive2019/blog/php-in-wp-article/#toc2

https://sologaku.com/wordpress/run-php-using-shortcode/#php%E3%82%92%E5%A4%96%E9%83%A8%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%8C%96%E3%81%97%E3%81%A6%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%B3%E3%83%BC%E3%83%89%E3%81%A7%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80%E6%96%B9%E6%B3%95

エス技研
ob_start、ob_get_contents関数でPHPの標準出力をバッファリング・変数に代入 標準出力をバッファリングし変数に代入することができるob_start()関数の解説。include()の処理をバッファリングすることで自由な場所に処理を記述することが可能。早い話...

(2024/3 追記分)https://marycore.jp/prog/php/fatal-error-cannot-redeclare-function/

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

エンジニアの私が大好きな、ガジェット/オーディオ機器 のレビュー&自作 を中心に
日々の生活におけるお役立ち備忘録を目指します。

※Amazonのアソシエイトとして、当メディアは適格販売により収入を得ています。

コメント

コメントする

目次