csv読み込みなどして、wp_insert_post()を動かしているとき。投稿数が増えるにつれて、遅くなってしまって困りました。
そんなとき見つけたこちらのページ。
wp insert post - Faster way to wp_insert_post & add_post_meta in bulk - WordPress Development Stack Exchange
【下書き】で投稿する
wp_insert_post()をするとき、post_statusをpublishにすると、投稿スラッグを自動で付ける作業が発生するため、遅くなります。
※特に同じタイトルで何件も投稿する場合。
注意
あとから「公開」に変更する作業が必要なのはもちろんのこと、get_posts()で取得する場合にも注意が必要です。post_statusがデフォルトでpublishになっているため、下書き状態の投稿を取得するには
<?php
$args = array(
"post_status" => "draft"
);
$posts = get_posts($args);
と明示する必要があります。
タームとコメントのカウント機能を一時的にオフにする
wp_defer_term_counting() | Function()
wp_defer_comment_counting() | Function()
trueにすると、タームとコメントのカウント機能をオフできます。処理プログラムの最初にtrueにして、最後にfalseにします。これにより、処理速度をスピードアップさせることできます。
サンプルコード
data.csvの例
p-0002,7000,スーパー薬草
p-0003,9000,デラックス薬草
<?php
wp_defer_term_counting( true );
wp_defer_comment_counting( true );
//テーマフォルダ内のCSVファイルを読み込む
$file = new SplFileObject(get_theme_file_path("data.csv"));
$file->setFlags(SplFileObject::READ_CSV);
while(!$file->eof()) {
//現在行データを取得
list($product_id, $price, $product_name) = $file->current();
//※データチェックする
// 投稿オブジェクトを作成
$my_post = array(
'post_title' => '投稿タイトル',
'post_content' => '本文',
'post_status' => 'draft'
);
// 投稿をデータベースへ追加
wp_insert_post( $my_post );
$file->next();
}
wp_defer_term_counting( false );
wp_defer_comment_counting( false );
重複チェックをする場合
上のサンプルコードのように、例えば商品データを投稿しているとき、投稿IDとは別に商品IDを重複させたくない場合。
1件ずつget_posts()してチェックしてたんですが、投稿数が増えると時間がかかります。
<?php
wp_defer_term_counting( true );
wp_defer_comment_counting( true );
$file = new SplFileObject($csv_path);
$file->setFlags(SplFileObject::READ_CSV);
//50行ずつ処理する
$max = 50;
while(!$file->eof()) {
//現在行
$current_line = $file->key();
//func関数内で50行ずつ処理
func($file, $max);
//50行進める
$file->seek($current_line + $max);
}
function func($file, $max){
$new_post_data = $product_ids = array();
$cnt = 0;
// ファイル取得してデータ作成
while(!$file->eof() && $cnt < $max) {
//何行進んだかカウント
$cnt++;
//現在行データを取得
list($product_id, $price, $product_name) = $file->current();
/*ここでデータチェックする*/
//投稿用データを作成
$new_post_data[$product_id] = array(
"post_data" => array(
"post_title" => $product_name,
"post_content" => "",
"post_status" => "draft"
),
"meta_data" => array(
"product_id" => $product_id,
"price" => $price
)
);
//重複チェック用
$product_ids[] = $product_id;
$file->next();
}
//同じ商品IDを持つ投稿を探す
$args = array(
"post_status" => array("private", "draft"),
"meta_key" => "product_id",
"meta_value" => $product_ids,
"meta_compare" => "IN"
);
if($posts = get_posts($args)){
foreach($posts as $post){
$exist_post_id = $post->ID;
$exist_product_id = get_field("product_id", $exist_post_id);
//この商品IDは投稿済みなので投稿用データから削除
unset($new_post_data[$exist_product_id]);
}
}
//投稿していく
foreach($new_post_data as $product_id => $data){
// 投稿をデータベースへ追加
$new_post_id = wp_insert_post($data["post_data"]);
if(!$new_post_id){
continue;
}
//カスタムフィールドを更新
foreach($data["meta_data"] as $key => $value){
update_post_meta($new_post_id, $key, $value);
}
}
}
wp_defer_term_counting( false );
wp_defer_comment_counting( false );
50行ずつ読み込んで処理するとタイムアウトすることがなくなりました。