2011年8月11日木曜日

プログラマからみたWordPress(データ構造)

言葉としてはよく聞いていた、WordPress。
最近少し触ってみたので、プログラマからみた感想を書いてみようエントリです。
しかも、データ構造をみれば何となく中が想像できるだろう...という勝手な視点からw
(まだ1週間しか触っていないので違うところがあったらゴメンナサイ)

まず....WordPress とは
Movable Typeと同じようにブログを書くためのソフトウェア。
MySQLとPHPの組み合わせで動きます。
いろいろカスタマイズできるのですが、「元々はブログを書くために生まれ、拡張されていったのね 」という認識を捨てないのが大事です(笑

登録画面からみたデータ構造


ページとして投稿できるものとしては2種類。
- 投稿 : ブログの投稿用のもの。カテゴリ、タグの設定が可能。親ページの指定はできない。
- 固定ページ : カテゴリ、タグの設定はできない。親ページの指定はできる。

メタ情報として2種類
- カテゴリ : 親子関係がある。
- タグ : 親子関係なし。

投稿、固定ページともに「カスタムフィールド」があり、メタ情報をお好みで追加できる。

DBからみた構造


テーブルの数は11個。思ったより少ない。中身をみてみると... 注目すべきテーブルは5つ。

wp_***_posts

投稿、固定ページ情報が入っているテーブル。
登録内容や動きは違うけど、テーブルは一緒で、"post_type" という属性により切り替わっている。

"post_type" の値は主に以下が入っているっぽい。
- post : 投稿の情報
- page : 固定ページの情報
- nav_menu_item : 設定画面でメニューを設定したときの情報
- attachment : 投稿/固定ページで設定した画像などの情報
- revision : 投稿/固定ページのリビジョン情報

テーブルのPrimaryKeyは「ID」
つまり、上記の情報は種類は違うけどIDはかぶらないはずということ。

また、「カスタム投稿タイプ」によって上記以外の "post_type" のものを作成する事ができたりもします。

PHP内では、get_post というメソッドでID指定すると、このテーブルの情報がとれる。
(論理的にはそうなんだけど、固定ページ用に get_page というメソッドも用意されているので、該当メソッドを使った方がコードの可読性はよい)

もうひとつ、get_posts というメソッドで条件指定で複数のPOSTを取得できるメソッドがあるけど、引数で設定するのはテーブルの項目とは一致しない。
また、post_type のデフォルトは "post" なので、違うタイプは明示的に指定が必要。
(こちらも固定ページ用に get_pages というメソッドが用意されている)

wp_***_terms

カテゴリ、タグ が入っているテーブル。
テーブル項目は
- term_id (Primary Key)
- name (表示名)
- slug (URLの一部として使われる文字)
- term_group (グループ化できそーだけどどこから設定するのか不明)

と4つだけ。term_idがPrimaryKeyだけど、使用者としてはslugがkey項目として使う感じ。
なのでこのテーブルに入っているものでslugは重複したらNG。
(WPの入力画面上で、重複したslugをいれられると、勝手に後ろに -2とかがつく)

PHP内で情報を抜き出すには、
カテゴリの場合は get_category, タグの場合は get_tagというメソッドで、term_idを渡すと取得できるのだけど、その中で呼ばれているのは結局、
get_terms というメソッド。 (想像どおりw)

wp_***_term_taxonomy

wp_***_terms に、カテゴリ、タグの区別情報は入っていません。
区別情報が入っているのがこのテーブル。
テーブル項目は、以下。
- term_taxonomy_id (PrimaryKey)
- term_id
- taxonomy
- parent (親taxonomyのid)
- count

"taxonomy"項目には以下の情報がはいっているっぽい。
- category : カテゴリ
- post_tag : タグ
- nav_menu : 設定画面でメニューを設定したときの情報

つまり、カテゴリとタグは 親がつけれる/つけれない の差があるけど、変更はこのテーブルの値を変えるだけで切り替えができるということ。

「カスタム投稿タイプ」同様、taxonomyも自作できる機能があるのですが、その情報はここに入ります。

wp_***_term_relationships

taxonomyとpostをひもづけているのが多分このテーブル。
テーブル項目は、以下。
- object_id
- term_taxonomy_id
- term_order

object_id は wp_***_postsのID が入っている。(多分)

wp_***_postmeta

画像などのattachmentのID情報、投稿/固定ページで設定できる「カスタムフィールド」の値はこのテーブルに入ります。
テーブル項目は、以下。
- meta_id (PrimaryKey)
- post_id
- meta_key
- meta_value

meta_keyには
ページで指定しているアイキャッチの画像の場合は "_thumbnail_id"が入っています。
カスタムフィールドの場合は、指定したkeyがそのままmeta_keyにはいります。
他にもいろいろメタ情報の登録があるのですが、ぱっと身、WPが自動登録してくれるものは _ から始まるkeyのようなので、カスタムフィールドのkeyには _ から始まらないもの の方がよさそうです。

ページで指定しているアイキャッチ画像は、the_post_thumbnail とかでズバっと画像出力ができるようになっていますが、設定項目を抜き出したい! という時には
「postmetaからIDを取得して、postsから情報抜き出す」ということで可能です。
$post_thumbnail_id = get_post_thumbnail_id($post->ID);
$attachment = get_post($post_thumbnail_id);

カスタムフィールドの値も同様に get_post_customというメソッドが用意されています。


ながながと書いてしまいましたが、データ構造を俯瞰して分かる事としては...こんなこと。

* カテゴリ/タグ には メタ情報追加は構造的に無理!

* 投稿/ページ には 複数のtaxonomy(カテゴリ/タグ)をつけれるが、taxonomyの親は一つだけしか構造的に無理!

* あるカテゴリ/タグに紐づくpost情報を抜き出すのは結構joinしていてコスト高い!
(そのため、内部ではキャッシュしているっぽいコードがある)

* 今後、WPがバージョンアップして機能追加した時は post_type とか taxonomy の値で新しい種類のものが追加される可能性が大きい。
つまり、カスタム投稿タイプ/taxonomy のkey名は、WPがversionアップ(機能追加)してもつけられないであろう名前にしておく方が無難。

* この記事が何回表示されてるとか 値を持ちたい時には、プログラムから wp_***_postmetaに バシバシいれたらよいかも。ただしkeyがかぶらなければ。
pluginも使うかもかもしれない = 違うpluginで同じkey値を偶然に使っていた場合はチョー怖いね。

* リビジョンを保持するようにすると、postテーブルに入っちゃうのでレコード数がガンガン増える!
リリース前は少なくともリビジョンは外して登録しておいた方が何となくよいよーな気もする。

かな。
• • •