WordPress のデータベースをブラウザからダンプする簡易な PHP スクリプト
先日放映された『フィニアスとファーブの35時間テレビ カモノグルメ博覧会』を時間の許す限り楽しんでいた kagata です。特にカモノグルメ評論家の多田野曜平氏は Twitter トレンド入りを果たしたそうで、たいへん目覚ましい活躍でしたね。
さて、今回は WordPress の運用で必要に迫られて書いた、ちょっとした PHP のスクリプトをご紹介します。これ自体がそのまま便利に使えるシチュエーションは限られそうですが、WordPress のカスタマイズや PHP のコーディングのヒントになるかもしれません。
要件
WordPress の運用案件で、次のような機能が必要になりました。
- ブラウザから WordPress のデータベースをダンプしたファイルがダウンロードできること
- ただし、できるだけサーバー上へのファイル作成を避けること
- WordPress のマルチサイト化に対応すること
1番目だけなら、あまた公開されている WordPress のバックアップ関連プラグインから適当なものを導入すれば解決できそうです。
しかし2番目がちょっと問題です。バックアッププラグインには、自動でディレクトリを作ってダンプファイルなどをためていくものが多いですが、今回の場合こういうタイプのものは使えないことになります。
いろいろ試したうち、プラグインでは WP Migrate DB が希望に近いようです。しかし残念ながら、3番目の条件にあるマルチサイト環境ではうまく動作しませんでした。
そんなわけで、今回は自分でいちからツールを作ってみることにしました。
WordPress のデータベースをダンプする
書いたコードはこちら。
<?php
require_once __DIR__ . '/wp-config.php';
// ファイルをダウンロードするよう Content-Type を指定
header('Content-Type: application/force-download');
// ダウンロードするファイル名を指定
$disposition = 'Content-Disposition: attachment; filename=%s_dump.sql';
header(sprintf($disposition, date('Ymd')));
// wp-config.php に記載された認証情報をもとに mysqldump を実行
$command = 'mysqldump %s -u %s -p"%s"';
passthru(sprintf($command, DB_NAME, DB_USER, DB_PASSWORD));
WordPress をインストールしたディレクトリ(wp-config.php のあるディレクトリ)にこのスクリプトを置き、ブラウザからアクセスすれば、ダンプファイルがごろっとローカルに落ちてくるという寸法です。
ポイントは次の2点です:
- Content-Type を application/force-download にする
ファイルをダウンロードさせたい場合、Content-Type を application/octet-stream とする例もよくあります。しかし、これでは Chrome では PDF などブラウザ内で表示できるものはダウンロードしてくれない場合があるようです。もっとも、今回はダウンロードするファイルの拡張子が .sql なのであまり関係なさそうではあります。 passthru()
でmysqldump
の結果を取得passthru()
はシステムコマンドの出力を PHP の標準出力に流してくれます。
WordPress にログインしているユーザーにのみダンプを許可する
ところで、上のスクリプトをいきなり公開環境に置いてしまっては、スクリプトを起動する URL さえ知っていればだれでもデータベースの中身を見ることができてしまいます。そこで最低限のケアとして、WordPress にログインしているユーザーにだけダンプを許可するという処理を追加してみました。
<?php
require_once __DIR__ . '/wp-config.php';
// WordPress にログインしていなければ、WordPress ログイン画面にリダイレクトする
if (!is_user_logged_in()) {
auth_redirect();
}
// 以降は先ほどと同様の流れ
header('Content-Type: application/force-download');
$disposition = 'Content-Disposition: attachment; filename=%s_dump.sql';
header(sprintf($disposition, date('Ymd')));
$command = 'mysqldump %s -u %s -p"%s"';
passthru(sprintf($command, DB_NAME, DB_USER, DB_PASSWORD));
WordPress の関数 is_user_logged_in()
で WordPress へのログイン状態を確認し、ログインしていなければ関数 auth_redirect()
で ログイン画面にリダイレクトしてしまいます。
WordPress Codex には、外部 PHP アプリケーションから WordPress を利用する方法として wp-blog-header.php をインクルードする方法が紹介されています。最初に思い浮かんだのはこの方法だったのですが、wp-blog-header.php をインクルードすると、その先で HTTP 応答ヘッダを出力できません。
今回のように is_user_logged_in()
や auth_redirect()
を使うだけなら、wp-config.php さえインクルードすれば十分なようですね。これは勉強になりました。
ちなみに、WordPress の本来の処理の流れでは次の順に PHP ファイルが読み込まれます。
- index.php が起動される
- index.php が wp-blog-header.php を読み込む
- wp-blog-header.php が wp-load.php を読み込む
- wo-load.php が wp-config.php を読み込む
参考:WordPressの実行フローを視覚化してみる | Simple Colors
まとめ
- ファイルをダウンロードさせる場合の Content-Type は application/force-download が便利
passthru()
を使えばシステムコマンドの出力を PHP の標準出力に渡せる- wp-config.php をインクルードすれば、WordPress へのログイン状態を外部 PHP アプリケーション側から知ることができる