私は製品データベースを含むウェブサイトを構築しています。各製品はカテゴリに属します。カテゴリの構造は、多層であり、例えば階層の任意の数を含むことができる:>Long Sleeved
MySQL/PHP - マルチティアカテゴリ構造
Electronics
>Games Consoles
>Xbox
>Xbox One
>Games
>etc..
Fashion
>Mens
>Shirts
私は常に、製品をティアの「最後の」カテゴリに割り当てます。ここで
は私のカテゴリテーブルの構造である:
id name parent_id ================================ 1 Fashion NULL 2 Mens 1 3 Shirts 2 4 Long Sleeved 3 5 Short Sleeved 3
私は自分のアプリケーションフレームワークとしてYii2を使用していますが、同じ概念は、ほとんどのMVCフレームワークに適用されなければならない、などのORMを実装する少なくともこれらActiveRecord。私が何をしたいか
は次のとおりです。すべてのカテゴリレベルの場合
- 、「マスター」の親を取得します。私。
Shirts
の場合Fashion
- いずれのカテゴリレベルでも、階層内のすべての「最後の」レベルカテゴリを取得します。私。
Mens
の場合、Long Sleeved
とShort Sleeved
となります。 - (さらに高度な)どのカテゴリレベルでも、それが持つ子/親の数を調べることができます。
I持って私のモデルでは、次のデフォルトの関係:
public function getParent() { return $this->hasOne(Category::className(), ['id' => 'parent_id']); } public function getParent() { return $this->hasMany(Category::className(), ['parent_id' => 'id']); }
次のいずれかの特定のカテゴリのための「木」を出力し、私が作成した関数です。
public function getParentTree() { $array = []; // $this->parent refers to the 'getParent()' relation above if(!empty($this->parent)) { $array[] = $this->parent->name; if(!empty($this->parent->parent)) $array[] = $this->parent->parent->name; if(!empty($this->parent->parent->parent)) $array[] = $this->parent->parent->parent->name; } else $array[] = "(none)"; $output = implode(" --> ", array_reverse($array)); return $output; }
しかし、ここにはたくさんの繰り返しがあり、それは醜く見えます。しかし、おそらく私は間違ったアプローチをとっており、データベース自体を再構築する必要があると私は信じています。
- 、「マスター」の親を取得します。私。
あなたは 'parent_id'で正しい軌道に乗っています。オンラインのツリービルダーを見つけたり、関数を再帰的にすることができます。つまり、現在の要素に親があるかどうかをチェックし、親を配列に追加し、親に対して同じ関数を実行します(これはツリー全体を反復処理します)。 – JimL
http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ – Barmar
parent_idは、カテゴリテーブルにデータを格納する理想的な方法ですが、カテゴリパスをインデックスに登録して、何をやっているのか再帰を避ける必要がある場合。この情報をYiiのキャッシュに保存したり、SQLクエリで利用できるパスインデックスが必要な場合は、カテゴリ構造を変更しながらこのテーブルを更新してカテゴリパスを格納するテーブルを作成できます。 – lucas