MySQL/PHP-多层类别结构


MySQL / PHP - Multi tier category structure

我正在构建一个包含产品数据库的网站。每种产品都属于一个类别。类别的结构是多层的,可以包含任何数量的层,例如:

  • Electronics>Games Consoles>Xbox>Xbox One>Games>etc..
  • Fashion>Mens>Shirts>Long Sleeved

我总是将产品分配到层中的"最后一个"类别。

这是我的分类表的结构:

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的框架。

我想做的是:

  1. 对于任何类别级别,获取"主"父级。即,对于Shirts,它将是Fashion
  2. 对于任何类别级别,获取该级别中的所有"最后"级别类别。即对于CCD_ 13,它将是CCD_ 14和CCD_
  3. (更高级)对于任何类别级别,请找出其拥有的儿童/家长数量

我的模型中有以下默认关系:

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;
}

但这里有很多重复,看起来很难看。但这也让我相信,也许我采取了错误的方法,需要重组数据库本身?

Bill我想我已经在YI2->Models中解决了这个问题。

下面是我的代码。

public static function getSubCategories($parent_id = NULL, $level = 0)
{
    // Get the Category from table
    // Here you can use caching Yii::$app->cache->get to avoid multiple queries
    $categories = Category::find()->select(['id', 'parent_id', 'name'])->where(['parent_id' => $parent_id])->asArray()->all();
    // Logic of Nth level to return
    self::$max_down_level += 1;
    if($level != 0 && self::$max_down_level > $level) return $categories;
    // Now for each sub categories find and return chidren as Array
    foreach($categories as $key => $category)
    {
        $categories[$key]['children'] = self::getSubCategories($category['id'], $level);
    }
    return $categories;
}

另外,不要忘记在模型类中声明public static $max_down_level = 0;变量。现在调用如下函数。

  1. 获取父类别self::getSubCategories(NULL)的所有子级
  2. 让所有孩子达到二级self::getSubCategories(NULL, 2)

与上面的方法相同,您可以声明用于获取父类别的递归函数。

public static function getParentCategories($parent_id, $level = 0)
{
    // Get the Category from table
    // Here you can use caching Yii::$app->cache->get to avoid multiple queries
    $categories = Category::find()->select(['id', 'parent_id', 'name'])->where(['id' => $parent_id])->asArray()->all();
    // Logic of Nth level to return
    self::$max_up_level += 1;
    if($level != 0 && self::$max_up_level > $level) return $categories;
    foreach($categories as $key => $category)
    {
        $categories[$key]['parent'] = self::getParentCategories($category['parent_id'], $level);
    }
    return $categories;
}

另外,不要忘记在模型类中声明public static $max_up_level = 0;变量。现在调用如下函数。

  1. 获取父类别self的所有子类别::getParentCategories(16,0)
  2. 让所有孩子达到二级自我::getParentCategories(16,2)

您可以使用自己的类名,而不是self

希望这能有所帮助。