QUOIT Blog

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

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

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

前提として、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->exe(
	"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"]=$db->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にデータが入ります。
一レコードの中にタグを配列としてまとめたかったので、一回リストを作って、そのタグを取得する、という方法を取っています。
($db->exe();はSQL実行して結果を得る、っていう僕の個人的なメソッドです。気にしないでください。)

解説

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

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

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

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

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

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

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

以上です。