2025年4月30日、手持ちの WordPress サイトについて「重大なエラー」ということでサイトにアクセスできなくなる問題が発生しました。実際にはキャッシュ系プラグインをいれていたおかげて、本日更新したか(キャッシュ更新した)、最近アクセスしていなかった(キャッシュがない)場合にのみでていたので、気づくのに少し時間がかかりました。
WordPress のデバッグを有効にしてみると、下記のようなエラーが表示されました。
Query Monitor というデバッグ用のプラグインもいれていたので、整理された状態でエラーがでてますね。原因は、「cal_days_in_month」関数が定義されていないよというもの

対処方法
暫定的な対応としては、FTPなどをつかってサーバーにある WordPress フォルダから、 wp-content > plugins に移動して、「backwpup」のフォルダを削除する、ということになります。ようするにプラグインを WordPress から消すということです。
今回の問題が修正されたあとに、改めてBackWPUP プラグインを新規インストールすれば、設定などはデータベース側に残っているのでそのまま使えるでしょう。
あるいは他のプラグインの乗り換えるという手もあります。
また、自前でバックアップシステムを構築可能なら、その方が安全かもしれません。
自前でバックアップシステムを構築する(技術者向け)
サーバーを管理運用している人対象、つまりはサーバーに ssh などでログインして、シェルスクリプトや cron などを使って自動バックアップなどを手掛けたりしているなら、参考になるかなと思います。
WP-CLI を利用したバックアップツールを作成して、下記に置きました。
UNIX系OSのサーバー管理をしているならわかるかなと思います。自由に使ってもらっても構いません。
WordPress には、WP-CLI というコマンドベースでユーザー制御したり、データベースからデータをバックアップしたり、プラグインや本体のアップデートなども可能なツールがあります。プラグインが WP-CLI に対応していれば、コマンドからプラグインの対応している機能を実行できたりします。BackWPUP も対応しており、WP-CLI を通じてバックアップを行うこともできます。
筆者も下記のような感じでバックアップしておりました。
Knowledge for WordPress: 複数サイトのメンテナンスを WP-CLI でやろう!(サーバー管理者編)
こうしたものを使えば
1. WP-CLI をサーバーにインストールする
*単体で実行可能。レンタルサーバーによっては wp コマンドとして存在する場合もあるがバージョンが古いこともある
2. WordPress のデータベースバックアップ
wp db export --default-character-set=utf8mb4
コマンド(4バイト UTF-8に対応)でSQL形式でバックアップできます。
3. WordPress本体を tar コマンドで tar.gz 形式でバックアップ
これらができれば、プラグインに頼らずともバックアップ可能になります。
ただ古いバックアップを削除するときには、下記のように7日より古いファイルは削除するなどの find コマンドなどの併用利用は必要になってくるでしょう。ただこのあたりはコマンドの意図するところを正しく理解できないなら、使うべきではありません。うっかり本体データごと削除してしまうおそれがあるためです。
find バックアップフォルダ/ -name "backup_*.tar.gz" -type f -mtime +7 -exec rm -f "{}" \;
以下、今回なぜこんなことが起こったのかをまとめておきます。
cal_days_in_month 関数が未定義のためにエラーがでた
PHPの公式ドキュメントによれば、年月をいれるとその月が何日あるのかを調べることができる関数のようですね。
PHP: cal_days_in_month - Manual
特に PHP8など最新版でも動作するようなので、これだけ見ると???という感じです。
いずれにせよ関数がないなら、Warningだけにとどめて無視してほしいという気持ちもありますが、それはそれで意図した動作をしないおそれもあるのでエラーで気づかせてくれるというのもまた必要ではあるので難しいところです。
cal_days_in_month 関数は標準で実装されていないかもしれない問題
下記をみると、Windows版 PHP にはこの関数は標準実装されているようですが、Linux OS 等が利用されてることも多い、レンタルサーバーなどでは明示的に別途 PHP を --enable-calendar オプションつきで実装(コンパイル)する必要があるようです。
PHP: Installation - Manual
https://www.php.net/manual/en/calendar.installation.php
手持ちのさくらインターネットのサーバーで、下記のようにテストコードを書いて、phpコマンドから実行すると、
<?php
ini_set('display_errors', "On");
cal_days_in_month(CAL_GREGORIAN,2,2025);
下記のように関数が定義されていないとエラーになります。
Fatal error: Uncaught Error: Call to undefined function cal_days_in_month() in /home/****/sample.php:4
Stack trace:
#0 {main}
thrown in /home/***/sample.php on line 4
さくらインターネットのWeb UIから、php.ini において下記を参考に
さくらのレンタルサーバのPHPの環境を確認、整えてみよう | さくらのホームページ教室
extension = calendar.so
をいれてみるも駄目。
phpinfo() コマンドで calendar 系のモジュールが入っているがどうか調べると、一応入っているのは入っているが、この関数が使えるものではなさそう。
% php -r "echo phpinfo();" |grep -i calendar
Calendar => Shane Caraveo, Colin Viebrock, Hartmut Holzgraefe, Wez Furlong
そのため、結局はプラグイン作者側が未定義関数がでそうなものについては、その関数がない場合のエラー処理をしてくれているのがよいということになるなぁという感じです。それ以前に、GitHub Actions 等標準的な環境での PHP Unit Test を開発者側もしてほしいものですね。もし、していても問題が発覚しないならどうしようもないですけれども...
2025年4月30日 @kimipooh