递归获取类别树(Yii)

时间:2012-07-14 11:58:12

标签: php recursion yii hierarchy

我有一个包含以下结构的表:

类别

  • ID
  • 名称
  • PARENT_ID

我想获得具有单一功能的类别树。 我在我的模型中写过这样的东西,但它不起作用。

public function getChildren($parent) { 
        $criteria = new CDbCriteria;
        $criteria->condition='parent_id=:id';
        $criteria->params=array(':id'=>$parent);
        $model = Term::model()->findAll($criteria);
        while ($model) {
            echo $model->id . "<br />";
            $this->getChildren;
        }
}

有人可以帮我吗?感谢。

4 个答案:

答案 0 :(得分:6)

我终于解决了这个问题。 如果有人感兴趣,这是代码:

public function getChildren($parent, $level=0) { 
        $criteria = new CDbCriteria;
        $criteria->condition='parent_id=:id';
        $criteria->params=array(':id'=>$parent);
        $model = $this->findAll($criteria);
        foreach ($model as $key) {
            echo str_repeat(' — ', $level) . $key->name . "<br />";
            $this->getChildren($key->id, $level+1);
        }
    }
public function getChildrenString($parent) { 
        $criteria = new CDbCriteria;
        $criteria->condition='parent_id=:id';
        $criteria->params=array(':id'=>$parent);
        $model = $this->findAll($criteria);
        foreach ($model as $key) {
            $storage .= $key->id . ","; 
            $storage .= $this->getChildrenString($key->id);
        }
        return $storage;
    }

答案 1 :(得分:1)

这是更好的解决方案。每个等级仅查询一个。其他解决方案使用每个孩子查询或查询所有记录(如果数量少则很好)

$models=Category::find()->where(['id'=>4])->one()->getRecursiveChildren();

public function getChild()
{
    return $this->hasMany(Category::className(), ['parent_id' => 'id']);
}
public function getRecursiveChildren()
{
    $models=[];
    $childs=$this->child;
    Yii::createObject(ActiveQuery::className(), [get_called_class()])->findWith(['child'], $childs);
    if(is_array($childs)&&count($childs)>0)
        foreach ($childs as $item)
        {
            $models[]=$item;
            $models=array_merge($models,$item->getRecursiveChildren());
        }
    return $models;
}

答案 2 :(得分:0)

您可以在模型中使用一个递归函数来执行此操作,如:

public function getCategoriesTree(&$tree = array(), $parentID = 0)
{
    $criteria = new CDbCriteria;
    $criteria->condition='parent_id=:id';
    $criteria->params=array(':id'=>$parentID);
    $resultNumber = $this->count($criteria);

    if($resultNumber > 0)
    {
        $model = $this->findAll($criteria);
        // get category position as order_id
        $orderId = 0;
        foreach ($model as $key) 
        {
            $tree[$orderId] = array(
                'id' => $key->id,
                'parent_id' => $key->parent_id,
                'name' => $key->name,
            );

            // get subcategories
            $this->getCategoriesTree($tree[$orderId]['subcat'], $key->id);

            if(count($tree[$orderId]['subcat']) === 0)
            {
                unset($tree[$orderId]['subcat']);
            }

            $orderId++;
        }
    }
}

并在控制器中使用它:

$model = new Categories;

    $tree = array(
        0 => array(
            'id' => 0,
            'parent_id' => -1,
            'name' => 'Main category',
            'subcat' => array()
        ),
    );

    $model->getCategoriesTree($tree[0]['subcat']);

答案 3 :(得分:0)

可能是这个帮助你......:)

我正在复制我的控制器类yii2的类别

<?php
namespace api\modules\v1\controllers;

use Yii;
use yii\rest\Controller;
use api\modules\v1\models\MySearializer;
use api\modules\v1\models\search\CategorySearch;
use api\modules\v1\models\Category;

class CategoryController extends Controller
{
    public function actionIndex()
    {
        $searchModel = new CategorySearch();
        $status        = false;
        $message       = '';
        $data          = (object)[];

        $dataProvider = $searchModel->search(Yii::$app->request->getBodyParams());
        $obj = new MySearializer();
        $obj->collectionEnvelope ='pager';
        $ser = $obj->serialize($dataProvider);
        return ['status' => true, 'message' => 'Category Listing', 
        'data' => $ser];
    }

    public function actionView($id)
    {
        $status        = false;
        $message       = '';
        $data          = (object)[];
        $model = Category::findOne($id);
        if($model)
        {
           return ['status' => true, 'message' => 'Category View', 
        'data' => $model];
        }else
        {
            return ['status' => false, 'message' => 'Category not found', 
        'data' => $data];
        }
    }

    public function actionAllParent()
    {
        $status        = false;
        $message       = '';
        $data          = (object)[];
        $model = Category::find()->where(['parent'=>0])->all();
        if($model)
        {
           return ['status' => true, 'message' => 'All Parent Category Listing', 
        'data' => $model];
        }else
        {
            return ['status' => false, 'message' => 'Parent Category not found', 
        'data' => $data];
        }
    }

    public function actionTree()
    {
        $status        = false;
        $message       = '';
        $data          = (object)[];
        $model = Category::find()->asArray()->all();
        $cattree = $this->CreateTree($model);
        print_r($cattree); die;
        if($model)
        {
           return ['status' => true, 'message' => 'All Child Category Listing', 
        'data' => $model];
        }else
        {
            return ['status' => false, 'message' => 'Child Category not found', 
        'data' => $data];
        }
    }

    public function actionChild($id)
    {
        $status        = false;
        $message       = '';
        $data          = (object)[];
        $model = Category::find()->where(['parent'=>$id])->all();
        if($model)
        {
           return ['status' => true, 'message' => 'All Child Category Listing', 
        'data' => $model];
        }else
        {
            return ['status' => false, 'message' => 'Child Category not found', 
        'data' => $data];
        }
    }

    public function CreateTree($tree,$parentId=0)
    {
        $branch =[] ;
        foreach ($tree as $element) 
        {
        if ($element['parent'] == $parentId) 
        {
            $children = $this->CreateTree($tree, $element['slno']);
            if ($children) 
            {
                $element['children'] = $children;
            }
            $branch[] = $element;
        }
       }
        return $branch;
    }
}