STERFIELD

2021/02/06

LaunchCartで直属の子カテゴリー一覧を取得する

LaunchCartで直属の子カテゴリー一覧を取得する

LaunchCartの商品やページのカテゴリーで、あるカテゴリー直属の子カテゴリー一覧を取得したい場合、
少しコツが必要です。

MySQLなどのRDBといわれるデータベースでは、カテゴリーのような階層構造を保存するために様々な方法がありますが(参考: 階層構造(入れ子集合モデル)について – Qiita)、
LaunchCartのカテゴリーでは、「入れ子集合モデル」という、構造が使われています(参考: 第5回 SQLで木構造を扱う~入れ子集合モデル (1)入れ子集合モデルとは何か :SQLアタマアカデミー|gihyo.jp … 技術評論社)。

例)

idlftrgtroot
1141
2231
3113

↑2が1の子であることを示している

入れ子集合モデルは複雑なツリー構造をRDBで実現するために誕生した画期的な階層構造の仕組みですが、
直属の子や親を取得するのには、ちょっと複雑な手続きが必要になります。

そのため、これまで直属の子カテゴリーを取得するために、様々な方法を試してきてましたが、
どれも重く、特にカテゴリーが大量に存在するモール系のECでは、実用に耐えない状況になっていました。

しかしながら、今回、比較的軽量で直属の子カテゴリー一覧を取得する方法に行き着くことができたので、紹介いたします。

LaunchCartの任意のテンプレート

こちらは、商品カテゴリーの例です。ページカテゴリーの場合は、’EcCoreBundle:ProductCategory’ を ‘PageCoreBundle:PageCategory’ に差し替えます。

ポイント

get_entity_manager()から始まるqueryBuilderで、rootが親カテゴリーと同じで [ .where(‘c.root = :root’) ]、且つ、lft、rgtがそれぞれ親カテゴリーの範囲に入っている[ .andWhere(‘c.lft > :lft’).andWhere(‘c.rgt < :rgt’) ]カテゴリーを取得します。
このとき、[ .orderBy(‘c.lft’, ‘ASC’) ] により lft の昇順で並び替えるのが、後から直属の子カテゴリーに絞り込むときに重要になります。

上記で取得したカテゴリーには、親の直属だけでなく、更に下層のカテゴリーが含まれています。
さらに、取得したカテゴリーを for文 でループさせ、それぞれのカテゴリーが、直前に絞り込んだ子カテゴリーの下層のカテゴリーでないかを判定し、
直属かどうかを絞り込みます。
このループで直属かどうかを判定できるのは、lftとrgtを使った階層構造の性質と、lft昇順で並び替えているためです。

今まで自分が模索した方法の中では一番早い方法でした。
もっといい方法もあるかもしれませんが、よろしければご利用ください。

キーワード:Symfony、Twig

Author Profile

著者近影

NINOMIYA

Webデザイナー兼コーダー出身のフロントエンド開発者です。 UXデザインやチーム開発の効率化など、勉強中です。

SHARE

合わせて読みたい