当前位置: 首页 > 后端技术 > PHP

贡献一个Laravel树结构管理包ClosureTable

时间:2023-03-30 03:40:00 PHP

关于Elegant树数据结构管理包,基于ClosureTable模式设计。github欢迎StarFeatures优雅树数据设计模式数据和结构分表,操作数据不影响结构EloquentTrait无需修改表即可轻松操作,兼容老数据完善的树操作方式支持生成树数据支持多种并存树(多根)支持节点/树修复支持软删除取决于php>5.6.0laravel>5.1.0关于ClosureTableClosure表是一种在任何RDBMS中存储和查询分层数据的简单而优雅的方式。分层数据是指一组数据,它们之间具有某种父子关系。我们通常使用“树”这个词来代替层次结构。举个例子,我们可以考虑地理位置之间的关系,如“国家”、“州/省”、“地区/城市”等。ClosureTable存储树中每个节点与其后代节点之间的关系,这将需要一个表name_closure来存储关系。部门表:idname1generalmanager2departmentmanager3administrator4secreterary一张基本的闭包表,包括ancestor,descendant,distance3个字段,如:ancestordescendantdistance1101211321432220231242330341440这个表记录了各个部门之间的关系,也记录了一个自关联。使用ClosureTable提供了大量的方法来操作树。影响树结构的方法makeRoot();//创建一个子节点,返回新的model$menu->createChild($attributes);//创建一个新的菜单,这个菜单此时没有连接,returnmodel$child=Menu::create($attributes);//添加一个已经存在的菜单到childlevel,$child可以是模型实例,模型实例集合或者id,包含id的数组,returnbool$menu->addChild($child);$menu->addChild(12);$menu->addChild('12');$menu->addChild([3,4,5]);//移动到$parent的下层,后代也会随之移动。$parent可以是模型实例或id,returnbool$menu->moveTo($parent);$menu->moveTo(2);$menu->moveTo('2');//与moveTo()$menu->addTo($parent)相同;//添加一个或多个同级节点,$siblings的后代也会随之移动,$siblings可以是模型实例集合或者id,一个包含id的数组,returnbool$menu->addSibling($siblings);$menu->addSibling(2);$menu->addSibling('2');$menu->addSibling([2,3,4]);//创建一个新的兄弟节点,返回新模型$menu->createSibling($attributes);//创建一个Self-association,returnbool$menu->attachSelf();//断开自身与所有后代的所有关联(该操作不保留子树,会使自身与所有后代隔离),returnbool$menu->detachSelf();获取数据的方法getDescendants();//获取所有后代,包括self,返回模式lcollection$menu->getDescendantsAndSelf();//获取所有祖先,返回模型集合$menu->getAncestors();//获取所有祖先,包括你自己,返回模型集合$menu->getAncestorsAndSelf();//获取所有孩子(直属),返回模型集合$menu->getChildren();//获取父母(直属上级),返回model$menu->getParent();//获取祖先(root),returnmodel$menu->getRoot();//获取所有siblings,返回modelcollection$menu->getSiblings();//获取包括自己在内的所有兄弟姐妹,返回模型集合$menu->getSiblingsAndSelf();//获取所有孤立节点Menu::getIsolated();Menu::isolated()->where('id','>',5)->get();//获取所有根Menu::getRoots();上面的get...()方法包含一个查询构造器,比如getDescendants()对应一个queryDescendants,可以在查询中添加条件查询或者排序。您可以使用$menu->queryDescendants()->where('id','>',5)->orderBy('sort','desc')->get();getRoot(),getParent(),getRoots(),getIsolated()4种方法没有查询构造函数如果只想获取包含单列或多列的结果可以在get...()方法中传参,如:$menu->getAncestors(['id','name']);由于数据库不需要parent_id列,如果你想在结果中显示包含该列的内容,可以在构造函数后面加上withParent(),如:$menu->queryDescendantsAndSelf()->withParent()->get()。默认的列名是parent。如果要自定义这个列名,在model中定义protected$parentColunm='parent_id'生成树Shape数据提供了多种方法生成树数据,可以从任意节点生成树getTree();//当前节点作为根生成树,按sort字段排序,returntree$menu->getTree(['sortColumn','desc']);//从根节点生成一棵树,returntree$menu->getRoot()->getTree();//树旁,不包括自己和下属,returntree$menu->getBesideTree();生成的树如下:['id'=>3,'name'=>'node3','children'=>[['id'=>4,'name'=>'node4'],['id'=>5,'name'=>'node5''children'=>[['id'=>6,'name'=>'node6']]]]生成树的childrenkey默认为children,如果要自定义,可以作为第二个参数传入,如:$menu->getTree(['sortColumn','desc'],'son');如果想得到只包含一列或多列的结果,可以作为第三个参数传入,如:$menu->getTree(['sortC列','desc'],'儿子',['id','name']);您的表可能包含多棵树,如果您想一一获取它们,您可以这样做:getTree();}$data=$mutiTree;判断isRoot();//是否为叶子节点$menu->isLeaf();//是否为孤立节点$menu->isIsolated();//是否有上级$menu->hasAncestors();//是否有下属$menu->hasDescendants();//是否有孩子(直属)$menu->hasChildren();//是否有直属上级$menu->hasParent();//$descendant是否是上级$menu->isAncestorOf($descendant);//$ancestor的下属是否为$menu->isDescendantOf($ancestor);//$parent是否是直接从属$menu->isChildOf($parent);//$child是否是直属上级$menu->isParentOf($child);//是否是$sibling的兄弟(同上)$menu->isSiblingOf($sibling);//If$beside如果你不是你自己或你的后代,则返回true$menu->isBesideOf($beside);数据维护perfectNode();//修复树关联,注意:这将循环整个树并调用perfectNode(),如果你的树非常大,这将花费很多资源,请谨慎使用$menu->perfectTree();install$composerrequriejiaxincui/closure-table构建树,需要新建一个闭包表如:menu_closureunsignedInteger('祖先');$table->unsignedInteger('后裔');$table->unsignedTinyInteger('距离');$table->primary(['祖先','后裔']);});在模型中使用Jiaxincui\ClosureTable\Traits\ClosureTableTrait。如果要自定义表名和字段,可以在模型中定义如下属性:$closureTable、$ancestorColumn、$descendantColumn、$distanceColumn。如果要自定义生成树数据的parent字段,在model中定义属性$parentColumn。下面的例子: