Edited at

WordPress 4.9.xで管理画面でのテーマファイルの編集に失敗するときの確認事項

More than 1 year has passed since last update.


WordPress 4.9.x系の管理画面でテーマファイルのPHPが編集できない

WordPressの4.9以降では管理画面でのphpファイルの更新が厳しくなっており、公式のリリースノートにも以下の記載があります。


安全のためのサンドボックス

真っ白な画面は非常に恐ろしいですね。WordPress 4.9はエラーがある状態で保存すると警告するので、テーマやプラグインに取り組んでいるときに白い画面を避けられるでしょう。夜はもっとよく眠れますね。

潜在的な危険を警告

テーマやプラグインを直接編集すると、WordPress 4.9はそれが危険なやり方だと警告します。そしてファイルを改変する前にバックアップするように勧めます。安全なルートを選べば、後から自分自身もチームと顧客もあなたに感謝することでしょう。


実際にWordPress 4.9.4にアップデートした後に管理画面でテーマファイルを更新しようとすると、「直接編集しないほうがいいよ」と以下のような警告がでました。

1.PNG

警告だから実は大丈夫なんじゃないか、と思ってそのまま以前のようにテーマファイルのphpを更新しようと「ファイルの更新」を押したら以下のエラーが発生して更新に失敗してしまいました。

2.PNG

日本語だと


致命的なエラーをチェックするためにサイトと通信できないため、PHP の変更は取り消されました。SFTP を使うなど、他の手段で PHP ファイルの変更をアップロードする必要があります。


英語だと


Unable to communicate back with site to check for fatal errors, so the PHP change was reverted. You will need to upload your PHP file change by some other means, such as by using SFTP.


というエラーです。

似たようなエラーで引っ掛かってる人で解決策はないかとググってみると、結構ハマっているひとがいました(バグなんじゃないか、って言っている人も)

公式が警告を出しているように、運用している画面でPHPのファイルが変更できてしまうと動作環境での資材とローカルや構成管理の資材との差分がでてしまって資材管理がおかしくなってしまったり、エラー画面を動作環境にリリースしてしまうリスクはあるため、ごもっともな機能です。

しかしデバッグログの仕込みやAPI疎通の確認のときにちょちょっと直すときには便利な機能なので、検証環境であればできればそのまま使いたいです。


原因調査と解決策

エラーの文言でWordPressのphpを検索してみると、どうやらwp-admin/includes/file.phpでファイルを更新するときに自分自身へリクエストを投げて正常終了するかどうか確認している模様。

https://github.com/WordPress/WordPress/blob/master/wp-admin/includes/file.php

        ...

$url = add_query_arg( $scrape_params, $url );
$r = wp_remote_get( $url, compact( 'cookies', 'headers', 'timeout' ) );
$body = wp_remote_retrieve_body( $r );
$scrape_result_position = strpos( $body, $needle_start );

$loopback_request_failure = array(
'code' => 'loopback_request_failed',
'message' => __( 'Unable to communicate back with site to check for fatal errors, so the PHP change was reverted. You will need to upload your PHP file change by some other means, such as by using SFTP.' ),
);
$json_parse_failure = array(
'code' => 'json_parse_error',
);

$result = null;
if ( false === $scrape_result_position ) {
$result = $loopback_request_failure;
} else {
$error_output = substr( $body, $scrape_result_position + strlen( $needle_start ) );
$error_output = substr( $error_output, 0, strpos( $error_output, $needle_end ) );
$result = json_decode( trim( $error_output ), true );
if ( empty( $result ) ) {
$result = $json_parse_failure;
}
}
...

ということは自分自身へのリクエストに失敗している?と思ってポート番号を確認してみたら、ブラウザ(8000)→ コンテナ(8000 → 80) → Apache(80)になっていた...orz

WordPressがApacheの8000ポートへリクエストを投げていて、Apacheの8000番ポートが空いていなかったのが原因でした。

設定をいじってブラウザ(8000)→ コンテナ(8000 → 8000) → Apache(8000)になるように設定を変えたら無事動きました。

WordPressは予約投稿のときのwp-cron.phpなど、自分自身へのリクエストで処理をすることが多いので、LB・CDN・リバプロ・IP制限などを間に挟んでいる構成の場合は、その辺の経路がうまく通ってないとハマるのでよく確認する必要がありそうです。

ということでまだまだ管理画面のテーマファイルの編集はまだまだ使えそうです(おい)


結論

WordPress自身へのリクエストのネットワーク経路が正しく動作するか確認してみましょう。