プログラミング備忘録(PHP、JavaScript、WordPress等)

WEB制作を行っている、とある個人事業主のプログラミングに関する技術メモをアウトプットしていきます。

WordPressのパンくずリストってどうやって生成されているのか?

はじめに

スクラッチで簡易的なECサイトを作ろうと思った時に、PHP+MySQL初心者の自分にとって最初の壁はパンくずリストです。 商品の追加やユーザー追加等はDBへのINSERT、DELETE、UPDATEなどで対応できますが、パンくずリストで先祖カテゴリまで取得ってどうするの?という疑問が生まれました。

ちょっと調べてみると、データベースの木構造を理解する必要がある、隣接リストが一般的だが毎回SQL文を発行するのはアンチパターンだ、など情報が入り乱れて整理ができないのです。 そこで、世界中で使われているWordPressの仕組みに乗っかれば大きく外さないのでは?ということで調べてみました。

WordPressパンくずリストは一般的に誰でも導入していると思います。ただ、仕組みまで理解している人はそれほど多くないのではないでしょうか。この関数をこういったループで回して・・といった使用方法に留まっているケースが大半?のはずです(違ったらごめんなさい)。 こんな記事でも誰かの参考になってくれると嬉しいです。

肝になるのはget_ancestors()

WordPressにおけるパンくずリストの仕組みとして、まずは現カテゴリのデータベースで保持しているparent情報を見て、親カテゴリが存在すればget_ancestors()が呼ばれます。

データベース構造例
ID カテゴリ名 親カテゴリID
1 カテゴリA 0
2 カテゴリB 0
3 カテゴリC 1
4 カテゴリD 3
5 カテゴリE 2

上記が隣接リストで、ツリーにすると以下の感じになります。

カテゴリA
├カテゴリC
 ├カテゴリD
カテゴリB
├カテゴリE

カテゴリDのページにおいて、パンくずリストを表示すると、
カテゴリA > カテゴリC > カテゴリD

になっておく必要がありますよね。

get_ancestors(カテゴリD, category)とすると、先祖カテゴリが配列で返ってきます。

Array
(
[0] => 3
[1] => 1
)

この仕組みを利用してみんなget_ancestorsを使うわけなんですが、本記事ではこの関数の中身を覗いてみます。
中はループになっていて、

  1. $term = get_term(現カテゴリID, category); 現カテゴリIDを$termにセット
  2. $ancestors[] = $term->parent; 親カテゴリIDを$ancestors配列にセット
  3. $term = get_term($term->parent, category); 親カテゴリIDを$termにセット

以降、親カテゴリIDが0になるまで2、3を繰り返す

結果的に、以下の配列が$ancestorsに格納されるという仕組みです。注意しないといけないのは、$ancestorsには深い階層のカテゴリIDから順番に配列に格納されていますので、array_reverse()関数で逆順にして操作した方が良いです。

Array
(
[0] => 3
[1] => 1
)

なお、get_term()内のget_instance()内でSELECT文を発行していることから、階層を1つずつSQL文で追っかけているんだと思われます。つまり、深い階層では何度もSQL文を叩いているので、大規模なサイトになるとデータベースに負荷がかかってきそうですね。

結論

簡易的なカテゴリ階層を作る際は、隣接リスト方式で実施する。
(もちろん、色々ご意見あると思いますので、アドバイスなどいただけると大変うれしいです)