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
(2024/3 追記分)https://marycore.jp/prog/php/fatal-error-cannot-redeclare-function/
コメント