🐥
WordPressでタイムアウトになる重い処理をCLI実装する
WordPressで全記事対象の処理などの重い処理を実行すると、タイムアウトエラーが出ることがある。処理されたレコードを確認して続きから実行するなどの方法があるが、本質的にはバッチ処理なのでSSHできる環境であればバッチ処理として実装すべきである。
具体的には、WordPressにはコマンドラインから実行できるWP-CLIという仕組みが用意されている。
WP-CLIを使うメリット
- タイムアウトの制限は受けない
- cronと組み合わせてバッチ処理できる
- スクリプト内ではWPQueryなどWordPress固有の機能がつかえる
WP-CLIの実行方法
eval-fileでWordPress環境下でPHPファイルを実行できる。
ターミナルでWordPressのインストールディレクトリにcdする場合
カレントディレクトリのWP環境を読み込んで、script.phpを実行する。
cd /path/to/wordpress
wp eval-file /absolute/path/to/script.php
カレントディレクトリがWordPressのインストールディレクトリでない場合:
--pathオプションでWordPressのインストールディレクトリを指定する。
実行内容は変わらないが、cdせずに1行のコマンドで実行できるメリットがある。
wp eval-file /absolute/path/to/script.php --path=/path/to/wordpress
ファイルの配置
WP-CLIの実行にあたり、バッチファイルはWordPress配下にある必要はない。
セキュリティを考慮すると、バッチファイルはインストールディレクトリ外に配置したほうがよさそう。
/var
|-- /www
|-- /yourdomain
|-- /public_html # ウェブアクセス可能
|-- /scripts # ウェブアクセス不可能
|-- batch.php
全記事更新するバッチのサンプル
<?php
/**
* 全投稿のタイトルを更新するスクリプト
*/
function update_post_titles() {
$offset = 0;
$batch_size = 50;
while (true) {
// WP_Queryを使用して50件ずつ投稿を取得
$args = [
'post_type' => 'post', // 投稿タイプ
'posts_per_page' => $batch_size,
'offset' => $offset,
'post_status' => 'publish' // 公開されている投稿のみ
];
$query = new WP_Query($args);
// 投稿がなければループを抜ける
if (!$query->have_posts()) {
break;
}
// 各投稿のタイトルを更新
foreach ($query->posts as $post) {
// 新しいタイトルの生成(元のタイトルに現在の日時を追加)
$new_title = $post->post_title . ' - Updated on ' . date('Y-m-d H:i:s');
// 投稿データの準備
$update_data = [
'ID' => $post->ID,
'post_title' => $new_title
];
// 投稿の更新
wp_update_post($update_data);
}
// メモリのクリア
wp_reset_postdata();
// 次のバッチのためにオフセットを更新
$offset += $batch_size;
}
echo "All posts have been updated.\n";
}
// タイトル更新関数の実行
update_post_titles();
Discussion