wordpressの投稿画面で「更新に失敗しました」と表示される

wordpressの投稿画面では、「更新に失敗しました」と表示されることがあります。個別に分解すると原因は様々だと思いますが、共通するところは、wordpress上で変数の受け渡しがうまくいっていないという点でしょうか。更新が出来ない現象は何も投稿画面だけでなく、wordpressのテーマやプラグインの編集画面でもよく出てきますが、この記事ではwordpressの投稿画面に限定します。

wordpressの投稿画面での「更新に失敗しました」の原因は?

更新できない原因を一言で説明すると、利用されているテーマかプラグインの中身のコードだと思います。もっとえいば、更新するために発生するwordpress上の処理プロセスが変わってしまったのが原因です。大きく変わったのは、wordpressのバージョン4.9からでしょうか。

更新に失敗してしまう具体的な原因は?

筆者の場合は、テーマの「functions.php」において$_GET['author']にempty関数を使い、空に対して空を代入していたためです。なんでこんな二度手間な処理をしているのかというと、こちらはphp7から未定義の変数をいきなり使うとNoticeエラーが出るようになったからです。ただ、プログラミング的には定義してから使うものです。

Notice: Undefined index: author in~

こんな感じに出ます。Notice(通知)はそれほど重要なエラーではないため、php.iniで「error_reporting = E_ALL」やwordpressのwp-configで「define('WP_DEBUG', false);」などと設定していないと出てきません。筆者の場合はこのエラーを消すために空の$_GET['author']に対して空を代入していました。issetやis_nullなどでは試していません。

wordpressの投稿画面でどうしたら更新できたか

「functions.php」に記述していた変数が問題でした。

更新できない

if(empty($_GET['author'])){$_GET['author']="";}
if($_GET['author']){

更新できた

if( !empty($_GET['author']) || preg_match('`/author/.+`', $_SERVER['REQUEST_URI']) ){

authorは何の変数?

$_GET['author']は、wordpressの管理者(著者)番号が入る変数です。$_GETでURL末尾に追記される「?」以降のパラメータの部分で指定します。なんでこの変数をwordpressテーマの「functions.php」で使っているかというと、外部からwordpressユーザ名を隠すためです。実は、wordpressのユーザ名って外部から簡単に見えたりします。ユーザプロフィールで「ブログ上の表示名」などという設定項目もありますが、curlコマンドでヘッダー情報を取得したり、wordpressのユーザプロフィールのURLのパラメータに1から順に数字を割り当ててアクセスすると、当該番号に対応するユーザ名がURLに含まれていたりします。事実上、「ブログ上の表示名」で本当のユーザ名が隠せていない、ということになります。(wordpressのパーマリンク設定で「?p=123」という形式を選択している場合はcurlコマンドで見えない)

また、wordpressの設定でニックネームと書かれていることから、おそらく登録した後でも手軽に変更できるようにという観点から考案されたシステムのような気がします。上記の通り、ブログ上で表示名を変えることができてもセキュリティを強化するものとはなっていません。

ユーザ名やIDが分かってしまうと、あらゆるパスワードを送り付けるブルートフォース攻撃が成立しやすくなります。wordpressへ何度かログインに失敗するとアクセス制限を発動するという防衛策もありますが、IPなどは偽装できますので、なるべくならログインIDなどは見えないほうが良いのです。

そして、逆パターンのリバースブルートフォースもありますが、こちらはパスワードに対してあらゆるIDを送信する手法であり、個人のwordpressブログだと効率が悪いので対象になりにくいと思います。一方、パスワードスプレー攻撃は複数のIDに予測できるパスワードを片っ端から送信するアタックであるため、上記のような手法で得たwordpressのユーザIDに対して短時間に片っ端からパスワードを送信されてしまうリスクはあります。

従って、wordpressを色々編集されているかたで上記の変数に問題があるケースであれば、それを見つけ出して改善するのが良いと思います。それが出来ない場合は、後述する他の方法を試してみると良いかも知れません。

「更新に失敗しました」を回避させる他の方法

まず、利用されているテーマをwordpressのオリジナルテーマ(標準)に変更してみて下さい。wordpressのデフォルトであれば、制作側もある程度動作確認してから公開しているでしょうから。それで「更新に失敗しました」と表示されなくなったら、高い確率で現在利用されているテーマが原因です。正常に動く他のテーマを利用する選択肢をご検討下さい。

また、有効化したテーマの「functions.php」と各プラグインのコードは、wordpressの管理画面を開くだけでも大抵読み込まれます。これらのファイルに上記のような変数に問題があると、「更新に失敗しました」と表示される可能性があります。そのため、プラグインも一旦無効化し、投稿画面で「更新に失敗しました」と表示されるかどうか確認してください。

無効化して「更新に失敗しました」と表示されなくなったら、その無効化したプラグインがおそらく原因です。代用できる他のものを探すか、自分で作れるなら自身で作成して対応すると良いでしょう。

最後の手段

「Classic Editor」をインストールして有効化します。これで以前の投稿システムに戻ります。このプラグインはWordPressの旧エディターと、TinyMCE、メタボックスなどを含む以前のスタイルの投稿編集画面レイアウトにするものです。しかし、このプログラムはいずれアップデートなどの修正が入らなくなるため、いつまでも使い続けるというもの良くありません。おそらく修正が入らなくなってもしばらくは利用できるでしょうけれど。ただ、タイムリミットつきの一番簡単な方法です。

まとめ

現在、wordpressで記事を投稿する際、更新ボタンを押しても以前のようにブラウザがページ全体を読込んではいないようです。フォームに入力された文字など、一部を読込んで変更していることと思います。これはajaxや非同期通信と呼ばれている技術です。

そして、通常のphpフォームではname属性を使い、同じphpプログラムを用いてPOSTやGETで値を受け取っています。しかしajaxではjavascriptとphpの間で値のやりとりをしており、name属性に加えてIDやclassなども併用されることがあります。

つまり、値の受け渡しがややこしくなっているため、wordpressでの編集にも影響が出ている訳ですね。wordpress誕生当時からこのシステムを導入していれば、こういった問題もほとんど発生しなかったと思うのですが、googleマップが出現する以前は、javascriptとphpの間で変数のやりとりをするなんていうことは一般的でなかったと思います。まあ技術の進歩で新しい試みが行われるのも仕方のないことなので、wordpressのこういった現象も当面は仕方のないことなのでしょう。