WordPress制作、カスタマイズ、Webシステム開発とSEO対策

外部から記事を登録したら予約投稿が作動しないので、WordPressの予約投稿のメカニズムを探ってみた

WordPressの「投稿」画面を使わないで、別のシステムから直接SQL文を発行して記事をぶっこむ仕様のWebアプリを製作中。

本題の前に、WordPressの主な記事ステータスについてご説明します。

WordPressの記事ステータス

記事ステータスとはつまりその記事がどのような状態で保存されているか、ということです。
主なものを紹介すると、

  • 下書き(draft)
  • 公開中(publish)
  • 予約投稿(future)
  • ゴミ箱(trash)

が代表的なところです。
他には

  • レビュー待ち(pending)
  • 自動保存(auto-draft)
  • 非公開(private)
  • リビジョン(inherit)

があります。

さて、今回開発していたWebアプリでは、あえてpublishedではなく、futureで記事を登録していました。
なぜかというと記事の公開時にTwitter連携をしていたのですが、最初からpublishedで登録すると、Twitter連携アプリが作動する「記事公開時フック」を通らないので、Twitterに記事が配信されなかったからです。
そこでわざと予約投稿にして、公開はWordPress側にさせることでフックを通そう、という算段です。

しかし、予約登録まではうまくいくものの、公開予定時間になってもwp-cronが作動せず、「予約投稿の失敗」になってしまう。

WordPressの予約投稿のメカニズム

未来の日付で記事が投稿された場合、WordPressの記事ステータスが「future」になります。
この状態で公開日時以降にそのWordPressのどこかにアクセスが有った場合、wp-cronが作動して記事の公開処理が行われます。
cronと言ってもサーバーで時限処理をするcronと違って、WordPressにアクセスされた時に日時を持って公開判定をするので、擬似的なcronといえるでしょう。

しかし、予約投稿には
・記事の日付
・記事のステータス

以外にも、DB上では情報の更新がありました。
今回WordPress上から投稿した時と何が違うのか調べてみると、単純に記事の投稿時刻とステータスだけではなく、wp_optionsの中の「cron」というテーブルに予約動作に関する情報が登録されていたのでした。

wp-optionsのcronを調べてみる

中をのぞいてみると、このレコードは記事予約の他にはakismetのスパム削除スケジュールなど、WordPressが扱う予約動作全般の情報を保存しておくものでした。
で、今回の予約記事に関しては

i:1368027884;
a:1:{s:19:”publish_future_post”;
a:1:{s:32:”2b1da4ca66a51f7e26369cbe52edd54f”;
a:2:{s:8:”schedule”;
b:0;
s:4:”args”;
a:1:{i:0;
i:567;

という情報が増えていました。
publish_future_postはこの予約動作の種類を、最後のi:567は記事IDを示している、といった程度は分かるのですが、「2b1da4ca66a51f7e26369cbe52edd54f」などはどうもWordPressが乱数を発生させて割り当てているようで、これを解析して再現するのは骨が折れそうです。

その労力を考えると、素直にWordPressのXML-RPC投稿を利用したり、Twitterの投稿アプリを追加開発したりしたほうが良さそうな気がします…。

普通に予約投稿が失敗する場合

こういうなにか特別なことをしてるわけではなく、普通に運用しているはずのWordPressで予約投稿がうまくいかない場合は、こちらの記事が参考になるかと思います。
WordPressの予約投稿が失敗する件の解決方法

Fatal error: Call to a member function get_results() on a non-object… の解決策

WordPressで、用意されているWordPress関数でなくオリジナルな挙動をする関数を自作するとき、便利なのが$wpdbクラスですね。
query、insert、get_resultsなど各メソッドの引数にSQL文を入れることによって、WordPressのMySQLデータベースから自由自在に結果を出し入れすることができます。

…と思ったら、あれっ?
フェイタルエラーが出てしまった!

Fatal error: Call to a member function get_results() on a non-object….
Fatal error: Call to a member function query() on a non-object….
Fatal error: Call to a member function insert() on a non-object….

はい。functions.phpの中の関数などにコードを余所からコピーしてきた場合など、上記のエラーが出て困った人も多いのではないでしょうか。

このエラーは「メンバー関数(メソッド)をオブジェクトでない場所で使おうとしてますよ」という意味です。

こんな時は慌てず

global $wpdb;

のグローバル宣言をそれより前に挿入します。
WordPress で DB にアクセスするには wpdb クラスを使います。グローバル変数 $wpdb でアクセスすることが可能です。
PHPでは、グローバル変数を関数の内部で使用する場合、関数の内部でグローバルとして宣言しておく必要があります。

上記はWordPressの例ですが、他のPHPフレームワークでも共通する原則なので、「困ったらグローバル宣言!」を忘れないようにしましょう!

WordPressマルチサイト時の画像アップパス&URLが変わった(3.5以降)

WordPressのマルチサイト運用時の画像のアップロードの取り扱いが変わったようです。私が気付いたのは3.5.1からだったんですが、3.5からの変更だったようです。

マルチサイト

  • サブディレクトリにインストールされた WordPress でもマルチサイト機能が利用可能に
  • ms-files.php をデフォルトで無効化
  • 新規インストールについてはファイル容量上限をデフォルトで無効化

Version 3.5 – WordPress Codex 日本語版”

これまでは、マルチサイト運用時には、
wp-content/blogs.dir/サイトID/files/
というディレクトリを作って、その中にファイルがアップロードされ、wp-includes/ms-files.php とmod_rewriteの働きによって
http://example.com/files/画像ファイル名.jpg
というURLで表示できるようになっていたわけです。

普通に、シングルの運用時のように/wp-content/uploads/ の中にアップしていたら、マルチサイトの画像が混ざってしまうからですね。

しかし3.5からはこのms-files.phpが無効になり、画像は
/wp-content/uploads/sites/サイトID/
にアップされ、
http://exanmple.com/wp-content/uploads/sites/サイトID/画像.jpg
で普通にアクセスするようになりました。
(さらに…)

WordPress「最新情報」欄の決定版! ページの更新情報とポストの投稿を合成して出力する

一般的な企業サイトには、必ずといっていいほどある「最新情報」欄。
「○月×日 ○○のページを更新しました」とか「○月×日 新製品のお知らせです」というもの。

しかしこの「○○のページを更新しました」というのが曲者なんですよね。

「ページを更新した」という情報は最新情報として伝えたいものの、そのためだけにわざわざ投稿を作成するのも面倒くさいし、その投稿の詳細ページが「○○のページを更新しました(リンク)」だけになってしまうのは間抜けだし、かと言って他に書くべきことも見当たらない。

そんなジレンマを解決する方法がこちらです。
ページの更新情報と、ポストの投稿を合成して、「最新情報」欄に出力します。
「投稿」はこれまでどおり投稿のシングル詳細ページに飛ぶけど、ページの更新情報はそのままページヘのリンクになるという仕組み。

(さらに…)

同じ日付の投稿記事の日付がうまく表示されない場合 「get_timeとget_date」

WordPressの投稿リストを出力してみたら、日付の部分がうまく表示されていない?

the_date()の表示

こんな現象に悩んだ方も多いのではないでしょうか。
KubrickしかりTwentyTen-twelveしかり、WordPressのデフォルトテーマは関数「the_date()」が標準になっています。
この関数は、日付規準での出力なので、「同じ日付の投稿がある場合は日付を重複して出力しない」という動作をするんですね。
(さらに…)