タイトルの通りです。以下のような状況となりました。
- PHPのスクリプト上のSQLで、WordPressのDBに直接postを下書きとしてインサート
- 下書きのpostのstatusをdraft->publishにするスクリプトを実行
- statusがなぜかfutureとして更新されてしまい自動で記事が公開されない
スクリプトの目的
2つスクリプトがあって、1つ目は下書きとして記事をDBに登録するもの、2つ目は下書きの記事を取得して公開にステータスに変更するものとなります。
なぜ一度下書きとして登録した後に公開するのか?
JetpackでTwitterに投稿を自動でツイートするようにしているのですが、SQLでDBにstatusを「publish」として直接インサートすると自動ツイートが上手く働いてくれないためです。
どういったスクリプト?
1つ目の記事をDBに登録するもの
以下となります。 $pdo
変数は事前に定義されてあるものとします。
以下のコードでDBに下書きとしてpostを保存することが出来ます。
$datetime = new DateTime(); $now = $datetime->format('Y-m-d H:i:s'); $datetime->setTimezone(new DateTimeZone('GST')); $now_gmt = $datetime->format('Y-m-d H:i:s'); $data = [ 'post_author' => 1, 'post_date' => $now, 'post_date_gmt' => $now_gmt, 'post_content' => $body, 'post_title' => $title, 'post_excerpt' => '', 'post_status' => 'draft', 'comment_status' => 'open', 'ping_status' => 'open', 'post_password' => '', 'post_name' => '', 'to_ping' => '', 'pinged' => '', 'post_modified' => $now, 'post_modified_gmt' => $now_gmt, 'post_content_filtered' => '', 'post_parent' => 0, 'guid' => '', 'menu_order' => 0, 'post_type' => 'post', 'post_mime_type' => '', 'comment_count' => 0, ]; $sql = "INSERT INTO wp_posts ( post_author, post_date, post_date_gmt, post_content, post_title, post_excerpt, post_status, comment_status, ping_status, post_password, post_name, to_ping, pinged, post_modified, post_modified_gmt, post_content_filtered, post_parent, guid, menu_order, post_type, post_mime_type, comment_count ) VALUES ( :post_author, :post_date, :post_date_gmt, :post_content, :post_title, :post_excerpt, :post_status, :comment_status, :ping_status, :post_password, :post_name, :to_ping, :pinged, :post_modified, :post_modified_gmt, :post_content_filtered, :post_parent, :guid, :menu_order, :post_type, :post_mime_type, :comment_count )"; $stmt= $pdo->prepare($sql); $stmt->execute($data);
2つ目の登録された下書きのpostを公開にするもの – 動作しなかったもの
こちらがDBから下書きの記事を取得して公開にするスクリプトです。
1つ目のものと違い、WordPressのloaderを読み込んでおり、WordPressの関数を使うようにしています。
require_once(dirname( __FILE__ ) . '/../wp-load.php'); $sql = "select * from `wp_posts` where `post_status` = 'draft' and `post_type` = 'post';"; $results = $wpdb->get_results($sql); foreach ($results as $key => $value) { $datetime = new DateTime(); $datetime->setTimezone(new DateTimeZone('Asia/Tokyo')); $publish_date = $datetime->format('Y-m-d H:i:s'); $post = get_post($value->ID); $post->post_status = 'publish'; $post->post_date = $publish_date; wp_update_post($post); }
解決策
2つ目のスクリプトが動かず色々試してみました。
post_date_gmt
をセットしてみたり、DBにデータを入れる時、statusをdraftではなく、future(公開予約)で既に入れてしまい、2つ目のスクリプトでfuture->publishに変更する等です。
ですが結論以下となりました。
require_once(dirname( __FILE__ ) . '/../wp-load.php'); $sql = "select * from `wp_posts` where `post_status` = 'draft' and `post_type` = 'post';"; $results = $wpdb->get_results($sql); foreach ($results as $key => $value) { $post = get_post($value->ID); wp_publish_post($post); }
wp_publish_post
という関数が用意されていて、こちらがWordPressで公開に必要な色々な処理を行ってくれているようでして、こちらを使用することで今回の問題が解決されました。
同じような問題で悩んでいる方の参考になればと思います。