WordPressの記事とタグをSQL直接発行で取得する

この記事は7年以上前の記事です。情報が古い場合がありますのでお気を付け下さい。

いろんな方がやってることとは思いますが、一応参考までに。
特にタグの部分に関しては結構悩んだので自分用のメモとして。

前提として、WordPressのDB構造はざらっと見ておいてください。

データベース構造 – WordPress Codex 日本語版

これを踏まえて、以下のコードで取得できます。

# wp-config.phpから下記をコピーする(wordpressのテンプレ内で書くなら必要ない)
define('DB_NAME', 'databasename');
define('DB_USER', 'user');
define('DB_PASSWORD', 'password');
define('DB_HOST', 'localhost');

$list=get("SELECT P.* FROM wp_posts P WHERE P.post_status = 'publish' ORDER BY P.post_date DESC limit 10");
foreach($list as $k=>$v){
  $list[$k]["tags"]=get(
    "select TS.name as tag from wp_term_taxonomy T "
    ."LEFT JOIN wp_terms TS ON TS.term_id = T.term_id "
    ."LEFT JOIN wp_term_relationships R ON T.term_taxonomy_id = R.term_taxonomy_id "
    ."LEFT JOIN wp_posts P ON P.ID = R.object_id "
    .sprintf("where R.object_id=%d ",$v["ID"])
    ."and T.taxonomy='post_tag' "
  );
}

function get($stmt){
  if (!mysql_connect(DB_HOST,DB_USER,DB_PASSWORD)) die("ERROR: HOST CONNECT FAILED");
  # CONNECT DB
  if (!(mysql_select_db(DB_NAME))) die("ERROR: DB CONNECT FAILED");
  if (!($data = mysql_query($stmt))) {
    echo mysql_error();
    return false;
  }
  $result = Array();
  while($tmp = @mysql_fetch_assoc($data)){
    array_push($result,$tmp);
  }
  if(!empty($result)){
    return $result;
  }else{
    return FALSE;
  }
}

#------------------------------
# ここから出力の処理
#------------------------------

echo "<table>";
echo "<tr>";
echo "<td>タイトル</td>";
echo "<td>本文</td>";
echo "<td>公開時間</td>";
echo "<td>タグ</td>";
echo "</tr>";
foreach($list as $k=>$v){
echo "<tr>";
echo "<td>".$v["post_title"]."</td>";
echo "<td>".$v["post_content"]."</td>";
echo "<td>".$v["post_date"]."</td>";
echo "<td>";
foreach($v["tags"] as $k2=>$v2){
echo "<p>".$v2["tag"]."</p>";
}
echo "</td>";
echo "</tr>";
}
echo "</table>";

tableタグ等は適宜変更してください。

具体的には、以下の箇所でデータを取得しています。

$db=new DB();
$list=$db-&gt;exe(
  "SELECT P.* FROM wp_posts P "
  ."WHERE P.post_status = 'publish' "
  ."ORDER BY P.post_date DESC "
  ."limit 10"
);
foreach($list as $k=&gt;$v){
  $list[$k]["tags"]=$db-&gt;exe(
    "select TS.name as tag from wp_term_taxonomy T "
    ."LEFT JOIN wp_terms TS ON TS.term_id = T.term_id "
    ."LEFT JOIN wp_term_relationships R ON T.term_taxonomy_id = R.term_taxonomy_id "
    ."LEFT JOIN wp_posts P ON P.ID = R.object_id "
    .sprintf("where R.object_id=%d ",$v["ID"])
    ."and T.taxonomy='post_tag' "
  );
}

これで$listにデータが入ります。
一レコードの中にタグを配列としてまとめたかったので、一回リストを作って、そのタグを取得する、という方法を取っています。

解説

このSQLを分解してみてみると、
1)記事を取得する
2)記事とタグを結びつけるテーブルから、紐づいたタグを取得する
という大まかな流れになっています。

ここで気をつけなければいけないのが、WordPressのDB構造。

ここからは「データベースでリレーションを組む」ということが理解できる方向けです。

すごく分かりづらいので個人的には嫌いなのですが、WordPressは下図のようなリレーションになってます。

黒字がテーブル名、青字がカラム名。(関係ないカラム名は省略してます)
赤線で書いたのが対応するキーです。

wp_postsに(下書きなども含む)記事が格納され、タグやカテゴリはwp_termsに入ります。

注意しなければいけないのは、例えばある記事につけていたタグを削除したとき、削除されるのはwp_term_relationshipsの関連付けデータのみであり、wp_termsにはデータとしてそのまま残っているということです。
リレーション構造からは当然なのですが、LEFT JOINの順序を間違えるだけでも正しいタグは取得できません。

以上です。

8年前