我有三张桌子:
brands(id, name)
categories(id, name)
subcategories(id, category_id, name)
加上产品表
products(id, category_id, subcategory_id, brand_id, [...])
我需要构建一个三级菜单,我很难在不查询数据库的情况下这么做。 基本上菜单就像这样
Electronics -> Smartphones -> Samsung
我的困难在于如上所述创建一棵树。我不能举例如Electronics -> Smartphones -> Nike(I have Nike as a brand, but in this category/subcategory combo Nike is obviously not needed)
。
到目前为止,我最终在循环内部循环只能获取每个组合所存在的品牌,但这会大大增加加载时间。
有更有效的方法吗?
最后,我希望得到以下内容
Electronics
Smartphones
Samsung
Apple
TVs
Samsung
Lg
Shoes
Sneakers
Nike
Converse
...
答案 0 :(得分:2)
根据产品表选择(没有空类别/子类别或品牌)
按品牌和子类别分组(无需使用相同的几行"组合"因为我们不需要在此处显示产品信息)
按字母顺序排序(按照您的意愿)
$sql = 'SELECT b.id AS brand_id, b.name AS brand_name, sc.id AS subcategory_id, sc.name AS subcategory_name, c.id AS category_id, c.name AS category_name
FROM products p
INNER JOIN brand b ON p.brand_id = b.id
INNER JOIN subcategory sc ON p.subcategory_id = sc.id
INNER JOIN category c ON sc.category_id = c.id
GROUP BY p.brand_id, p.subcategory_id
ORDER BY c.name ASC, sc.name ASC, b.name ASC';
然后在PHP中:
$lastCategoryId = 0;
$lastSubCategoryId = 0;
// Fetch results
while($result = // Fetch row) {
if ($result->category_id != $lastCategoryId) {
// This is the first time you see that category: display its name (and create a ul tag for example)
echo '<br />'.$result->category_name.'<br />';
$lastCategoryId = $result->category_id;
}
if ($result->subcategory_id != $lastSubCategoryId) {
// This is the first time you see that subcategory: display its name (and create a sub-ul tag for example)
echo '---'.$result->subcategory_name.'<br />';
$lastSubCategoryId = $result->subcategory_id;
}
// No need to check the last brand_id because in the SQL we can't have the same subcategory/brand twice, so it will always be a new brand for this subcategory.
echo '------'.$result->brand_name.'<br />';
}
*编辑:使用嵌套的ul / li(未测试)
$lastCategoryId = 0;
$lastSubCategoryId = 0;
// Main list
echo '<ul>';
while($result = // Fetch row) {
// Category level
if ($result->category_id != $lastCategoryId) {
// First time you see that category
// Re-init subcategory last id (so that later we can know if it's the first subcategory in this category or not)
$lastSubCategoryId = 0;
// Close previous category li (if $lastCategoryId == 0, means that there is no category to close, it's our very fist)
if ($lastCategoryId != 0) {
echo '</ul></li>';
}
// Open li element (which will contain category name + list of subcategories)
echo '<li>';
echo $result->category_name;
// Open sub-ul (which will contain subcategories list)
echo '<ul>';
}
// Subcategory level
if ($result->subcategory_id != $lastSubCategoryId) {
// First time you see that subcategory
// Close previous subcategory li (if $lastSubCategoryId == 0, means that there is no subcategory to close, it's our first one in that category)
if ($lastSubCategoryId != 0) {
echo '</ul></li>';
}
// Open li element (which will contain subcategory name + list of brands)
echo '<li>';
echo $result->subcategory_name;
// Open sub-sub-ul (which will contain brands list)
echo '<ul>';
}
echo '<li>'.$result->brand_name.'</li>';
}
// Close last subcategory
echo '</ul></li>';
// Close last category
echo '</ul></li>';
// Closing main list
echo '</ul>';
答案 1 :(得分:1)
非常确定具有内部联接的查询是您所需要的,除非您有某种方法将品牌映射到多个类别/子类别。
select c.name, sc.name, b.name
from brands b
inner join subcategories sc where sc.id = b.subcategory_id
inner join categories c where c.id = b.category_id
这将构建像
这样的结果Electronics Smartphones Samsung
Electronics Smartphones Apple
...
Shoes Sneakers Nike
等。如果您确实需要树形视图,可以使用其他选项对其进行格式化,但是您应该能够将结果打包成一个漂亮的数据结构。