codiverum / yii2-abstracttree
该扩展包含抽象类,为树状结构数据提供基础
dev-master
2015-07-16 19:09 UTC
Requires
- yiisoft/yii2: *
This package is not auto-updated.
Last update: 2024-09-14 16:50:23 UTC
README
该扩展包含抽象类,使在Yii2框架中实现树状结构数据变得简单。它包含层级数据所需的所有功能
- 多个根节点
- 选择父节点、子节点、兄弟节点、祖先节点、后代节点(也可以通过距离选择);对程序员和数据库管理系统都很容易。
- 修改树,如添加节点、删除节点和移动节点(带或不带子树);简单(基于
id_parent值的变化 - 所有工作都由AbstractNode类完成)
我发现了其他实现树状结构数据的方法(如嵌套集),但我不喜欢使用递归或子查询来执行像选择数据这样的频繁查询。我创建了自己的方法(我没有找到这种解决方案)。
我希望你会觉得它有用且简单。
这是我第一次开源作品,所以我很乐意听取任何建议。我相信这个小库可以改进。
基本设计将数据放入两个表中
- node
id INT PRIMARY KEY auto_increment,
id_parent_node INT DEFAULT NULL,
node_level INT NOT NULL
- 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']); } }
就是这样。