WordPress の更新情報を外部から php + SQL で取得する

WordPress の更新をプラグインに頼らず取得

WordPress の更新情報 (What’s new) を,表示してくれるプラグインなどは存在するようですが,WordPress 外部から更新情報を持ってくる方法がいまいち見つからなかったので自分で作ってみました.
(現在, http://congrazia.net/ に WordPress の更新情報を表示しています)

php + SQL で更新情報を取得

使ったのは php で直接 MySQL の DataBase からデータを持ってくる方法.
DataBase の構造は公式のここに載ってます.
(私は見ずに作ってしまいました……)
このサイトの画像のなかでは “wp_” が table 名の接頭辞として設定されているようです.
(この接頭辞,末尾を “_” にしなかった場合,テーブル名と接頭辞の間に何も文字が入らないので,インストール時は末尾に “_” を入れるのが無難そうです.私は “presto” にしたものだから,テーブル名が “prestoposts” とか,ひどいもので “prestoterm_relationships” とかになっています)
以下では接頭辞は “prefix_” と表記することにします.
ここをインストール時に設定した接頭辞にすれば各自の WordPress 環境の DataBase と同じものになるはずです.

最新記事を得る

記事の情報が保存されているのは,table “prefix_posts” ですね.
気をつけるのは,記事の状態の情報( “post_status”)のカラムです.
公開されているとか,下書きであるとかですね.公開中の記事は “publish” になっているようです.
ここまで分かれば簡単ですね.SQL は
“SELECT * FROM %sposts WHERE post_status = ‘publish’ ORDER BY post_date DESC LIMIT %d”
%s は接頭辞 “prefix_” 等, %d は取得する件数です.

記事の情報を取り出す

欲しいのは題名 field “post_title”, 更新日時 field “post_date”, そして URL くらいでしょうか.
勿論その他の情報 “post_author”, “ID” なども取得可能です.
URL については,少し複雑なので,次の”パーマリンク取得”で説明します.

パーマリンク取得

先ほど取得した記事情報ですが,記事の URL は “guid” で得られる……のですが,これはデフォルト設定のパーマリンク,いわゆる Ugly 形式です.
このままリンクに使っても記事には飛べますが,SEO 的にはよろしくないので,しっかり,指定してあるパーマリンク方式でリンクしてあげたいですね.
ということで,まずはパーマリンクのストラクチャー(フォーマット)を取得します.
パーマリンクのストラクチャーは table “prefix_options” の field “option_name” が “permalink_structure” のレコードの “option_value” の値ですね.
あとは,この permalink_structure の %hoge% を色々 replace するだけです.
%postname% なら “posts” の field “post_name” の値ですね.
しかし,やはりここでも,よく使ううちの幾つかは少々複雑な取得方法になります.
特に %category%, %tag%, %author% でしょうか.
%category% と %tag% はほぼ同じですし, %author% も言うほど変わらない取得方法なので,ここでは一番良く使うであろう(そして私もよく使っている) %category% のみを解説します.
もし要望や時間があれば他の 2 つも作るかもしれませんが.

category_slug の取得

さて,カテゴリスラッグですが,記事の id から取得するに必要なテーブルが 3 つあります.
“prefix_term_relationships”, “prefix_term_taxonomy”, “prefix_terms”
ですね.
それぞれ
“記事 id と それに付いている category や tag”, “category や tag とその種類”, “category や tag とその slug”
を関連付けるのに必要です.それぞれのテーブルを r, t, s とした時のそれぞれの field の対応は
“r.object_id (= post_id), r.term_taxonomy_id”, “t.term_taxonomy_id (= r.term_taxonomy_id), t.taxonomy (= category, (or tag))”, “s.term_id (=r.(or t.)taxonomy_id, s.slug)”
と言った感じです.
これでカテゴリスラッグにたどり着けます.
SQL にすると
“SELECT s.slug FROM (%sterm_relationships r INNER JOIN %sterm_taxonomy t ON r.term_taxonomy_id = t.term_taxonomy_id AND r.object_id = %d AND t.taxonomy = ‘category’) INNER JOIN %sterms s ON t.term_taxonomy_id = s.term_id ORDER BY s.term_id ASC LIMIT 1”
(正しい整形がわからないのでワンライナー.汚くてすみません.)
これの %s 全てに $prefix を, %d に “ID”(post_id) を入れたものになりますね.
“ORDER BY s.term_id LIMIT 1” としているのは, WordPress では 1 つの記事に複数のカテゴリを指定でき,また,カテゴリスラッグが必要なときは一番若い id を持つカテゴリのものが使われるからです.

実際に php + SQL で更新情報を取得してみた(ソース)

関数を幾つか作りました.
class を使ったほうが綺麗かしらとも思ったのですが,一旦この形で.
print_new を prefix(データベース接頭辞), $directory(ワードプレスのトップページのあるディレクトリ)で指定すれば5件の更新情報を引っ張ってきて,適当な html で出力します.
(他の関数は private だと思ってもらって構いません)
あくまで参考程度にお願いします.
try, catch は全然書いてませんが,使うときはのせることを推奨いたします.

ちょっと面倒なのは,MySQL の DATETIME は strtotime で一度 int に変換しないと使えない点.
結構ハマった.

<?php
/*
$sql_link = mysql_connect("$dtbhost","$dtbuser","$dtbpass");
mysql_select_db("$dtbname", $sql_link);
でデータベースに接続しておく.
*/

function print_new($prefix, $directory)
{

    $post_query = sprintf("SELECT * FROM %sposts WHERE post_status = 'publish' ORDER BY post_date DESC LIMIT 5", $prefix);

    $posts = mysql_query("$post_query");
    if (!$posts) {
        die('クエリーが失敗しました。'.mysql_error());
    }
    echo '<table class="whatsnew">'."\n";
    while ($post = mysql_fetch_assoc($posts)){
        $category_slug = get_category_slug($post, $prefix);
        echo '<tr>'."\n";
        echo '<th>'.date("Y/m/d", strtotime($post['post_date'])).'</th>'."\n";
        echo '<td>';
        printf('<a href = "/%s%s">%s</a>', $directory, get_solved_permalink(get_permalink_structure($prefix), $post, $prefix), $post['post_title']);
        echo '</td>'."\n";
        echo '</tr>'."\n";
    }
    if(mysql_num_rows($posts)==0){
        echo '<tr><td>まだ記事がありません</td></tr>';
    }
    echo '</table>'."\n";

    printf('<div class="foot"><a href="/%s/">More</a></div>', $directory);
}


function get_category_slug($post, $prefix)
{
    $id = $post['ID'];
    $get_category_query = sprintf("SELECT s.slug FROM (%sterm_relationships r INNER JOIN %sterm_taxonomy t ON r.term_taxonomy_id = t.term_taxonomy_id AND r.object_id = %d AND t.taxonomy = 'category') INNER JOIN %sterms s ON t.term_taxonomy_id = s.term_id ORDER BY s.term_id ASC LIMIT 1", $prefix, $prefix, $id, $prefix);
    $category_slug = mysql_fetch_assoc(mysql_query($get_category_query))['slug'];
    return $category_slug;
}

function get_permalink_structure($prefix)
{
    $get_permalink_query = sprintf("SELECT option_value FROM %soptions WHERE option_name = 'permalink_structure'", $prefix);
    $permalink_structure = mysql_fetch_assoc(mysql_query($get_permalink_query))['option_value'];
    return $permalink_structure;
}

/*
function get_author_name($post, $prefix)
{
    
}

function get_tag_slug($post, $prefix)
{
    
}
*/

function get_solved_permalink($structure, $post, $prefix)
{
    $year = date("Y", strtotime($post['post_date']));
    $month = date("m", strtotime($post['post_date']));
    $day = date("d", strtotime($post['post_date']));
    $solved = str_replace('%year%', $year, $structure);
    $solved = str_replace('%monthnum%', $month, $solved);
    $solved = str_replace('%day%', $day, $solved);
    $solved = str_replace('%category%', get_category_slug($post, $prefix), $solved);
    $solved = str_replace('%postname%', $post['post_name'], $solved);
    $solved = str_replace('%post_id%', $post['ID'], $solved);
    /*
    $solved = str_replace('%author', get_author_name($post, $prefix), $solved);
    $solved = str_replace('%tag%', get_tag_slug($post, $prefix), $solved);
    */
    return $solved;
}
?>

%tag% と %author% の置き換えは未実装.
%tag% は %category% とほぼ同じなので,簡単に動きそう(同じ関数にしてオプションで変更で良さそう)
%author% は %category% よりは楽になるかと思います.
%author% 名を変えるプラグイン等を入れていたら面倒くさそうですが.

まとめ

・MySQL の接頭辞は末尾に “_” をつけるのが無難.
・実は category と tag は同じ terms 扱い.
・WordPress といえども,DataBase の情報を整形などなどしているだけ.DataBase の中身を理解すれば十分自分で SQL 文を発行して色々できる.
・自分で CMS を作っていた経験はすごく役に立ったので,みなさんも簡単な CMS を作ってみてはいかが?