codiverum/yii2-abstracttree

该扩展包含抽象类,为树状结构数据提供基础

安装: 57

依赖: 0

建议: 0

安全: 0

星级: 2

关注者: 2

分支: 1

开放性问题: 1

类型:yii2-extension

dev-master 2015-07-16 19:09 UTC

This package is not auto-updated.

Last update: 2024-09-14 16:50:23 UTC


README

该扩展包含抽象类,使在Yii2框架中实现树状结构数据变得简单。它包含层级数据所需的所有功能

  • 多个根节点
  • 选择父节点、子节点、兄弟节点、祖先节点、后代节点(也可以通过距离选择);对程序员和数据库管理系统都很容易。
  • 修改树,如添加节点、删除节点和移动节点(带或不带子树);简单(基于id_parent值的变化 - 所有工作都由AbstractNode类完成)

我发现了其他实现树状结构数据的方法(如嵌套集),但我不喜欢使用递归或子查询来执行像选择数据这样的频繁查询。我创建了自己的方法(我没有找到这种解决方案)。

我希望你会觉得它有用且简单。

这是我第一次开源作品,所以我很乐意听取任何建议。我相信这个小库可以改进。

基本设计将数据放入两个表中

  1. node
id INT PRIMARY KEY auto_increment,
id_parent_node INT DEFAULT NULL,
node_level INT NOT NULL
  1. node_ancestor
id_node INT NOT NULL,
id_ancestor_node INT NOT NULL,

还设置了适当的外键。注意,名称可以轻松定制(请参阅下面的迁移部分)

安装

安装此扩展的首选方式是通过composer

运行以下命令

php composer.phar require --prefer-dist codiverum/yii2-abstracttree "dev-master"

或将以下内容添加到您的composer.json文件的require部分。

"codiverum/yii2-abstracttree": "dev-master"

使用

使用此扩展,您可以轻松地创建

  • 自定义迁移
  • 准备好使用的ActiveRecord类

迁移

要创建迁移,您应该创建新的迁移

yii migrate/create migration_name

您的迁移应该扩展codiverum\abstracttree\migrations\AbstractTreeBaseMigration类,例如

use codiverum\abstracttree\migrations\AbstractTreeBaseMigration;
use yii\db\Schema;

class m150505_194334_category_tree extends AbstractTreeBaseMigration {

    public function up() {
        parent::up();
        $this->addForeignKey('fk_category_usercreated', 'category', 'id_user_created', '{{%user}}', 'id', 'SET NULL', 'CASCADE');
    }

    public function getExtraNodeTableColumns() {
        return [
            'id_user_created' => Schema::TYPE_INTEGER,
            'name' => Schema::TYPE_STRING . '(128) NOT NULL',
            'description' => Schema::TYPE_TEXT,
            'created_at' => Schema::TYPE_INTEGER,
            'updated_at' => Schema::TYPE_INTEGER
        ];
    }

    public function getNodeTableName() {
        return 'category';
    }
}

然后使用以下命令应用迁移

yii migrate

模型

使用Gii生成关系表,您可以直接使用它。之后,您可以使用Gii生成主表的模型或自己编写它。只需确保您的类扩展了AbstractNode类。如果您做到了,您可以删除为默认列创建的关联(不在getExtraNodeTablesColumns迁移方法中),因为它们已经在AbstractNode类中涵盖了。您可能希望向类描述中添加内容(使用您的模型类名称而不是Category

 * @property Category $parent
 * @property Category[] $ancestors
 * @property Category[] $descendants
 * @property Category[] $children
 * @property Category[] $siblings

对于上面的迁移示例,Category类看起来像这样

namespace common\models;

use codiverum\abstracttree\components\interfaces\TreeNodeInterface;
use codiverum\abstracttree\models\AbstractNode;
use Yii;
use yii\db\ActiveQuery;
use common\models\User;

/**
 * This is the model class for table "category".
 *
 * @property integer $id
 * @property integer $id_parent_category
 * @property integer $id_user_created
 * @property string $name
 * @property string $description
 * @property integer $created_at
 * @property integer $updated_at
 *
 * @property User $userCreated
 * @property Category $parent
 * @property Category[] $ancestors
 * @property Category[] $descendants
 * @property Category[] $children
 * @property Category[] $siblings
 */
class Category extends AbstractNode implements TreeNodeInterface {

    public function beforeSave($insert) {
        if ($insert) {
            $this->id_user_created = Yii::$app->user->id;
        }
        return parent::beforeSave($insert);
    }

    /**
     * @inheritdoc
     */
    public static function tableName() {
        return 'category';
    }

    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [['id_parent_category', 'category_level', 'id_user_created', 'created_at', 'updated_at'], 'integer'],
            [['name', 'category_level'], 'required'],
            [['description'], 'string'],
            [['name'], 'string', 'max' => 128],
            [['name', 'id_parent_category'], 'unique', 'targetAttribute' => ['name', 'id_parent_category'], 'message' => 'The combination of Id Parent Category and Name has already been taken.']
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        return [
            'id' => Yii::t('db', 'ID'),
            'id_parent_category' => Yii::t('db', 'Id Parent Category'),
            'id_user_created' => Yii::t('db', 'Id User Created'),
            'name' => Yii::t('db', 'Name'),
            'category_category_level' => Yii::t('db', 'Category Level'),
            'description' => Yii::t('db', 'Description'),
            'created_at' => Yii::t('db', 'Created At'),
            'updated_at' => Yii::t('db', 'Updated At'),
            'parent.name' => Yii::t('db', 'Parent'),
            'userCreated.display_name' => Yii::t('db', 'Author'),
            'category_level' => Yii::t('db', 'Level'),
            'parent' => Yii::t('db', 'Parent'),
            'userCreated' => Yii::t('db', 'Author'),
        ];
    }

    /**
     * @return ActiveQuery
     */
    public function getUserCreated() {
        return $this->hasOne(User::className(), ['id' => 'id_user_created']);
    }

}

就是这样。