paxha/laravel-adjacency-list

使用CTE的递归Laravel Eloquent关系

v2.1.2 2019-11-24 10:54 UTC

This package is auto-updated.

Last update: 2024-09-24 22:20:15 UTC


README

Build Status Code Coverage Scrutinizer Code Quality Latest Stable Version Total Downloads License

简介

此Laravel Eloquent扩展通过使用公用表表达式(CTE)提供递归关系。

支持Laravel 5.5.29及以上。

兼容性

  • MySQL 8.0+
  • MariaDB 10.2+
  • PostgreSQL 9.4+
  • SQLite 3.8.3+
  • SQL Server 2008+

安装

composer require paxha/laravel-adjacency-list

用法

入门

考虑以下表架构用于分层数据

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('parent_id')->nullable();
});

在模型中使用HasRecursiveRelationships特性以处理递归关系

class User extends Model
{
    use \Paxha\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;
}

默认情况下,特性期望一个名为parent_id的父键。您可以通过覆盖getParentKeyName()来自定义它

class User extends Model
{
    use \Paxha\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;
    
    public function getParentKeyName()
    {
        return 'parent_id';
    }
}

关系

特性提供各种关系

  • ancestors():模型的递归父级。
  • ancestorsAndSelf():模型的递归父级和自身。
  • children():模型的直接子级。
  • childrenAndSelf():模型的直接子级和自身。
  • descendants():模型的递归子级。
  • descendantsAndSelf():模型的递归子级和自身。
  • parent():模型的直接父级。
  • parentAndSelf():模型的直接父级和自身。
  • siblings():父级的其他子级。
  • siblingsAndSelf():所有父级的子级。
$ancestors = User::find($id)->ancestors;

$users = User::with('descendants')->get();

$users = User::whereHas('siblings', function ($query) {
    $query->where('name', '=', 'John');
})->get();

$total = User::find($id)->descendants()->count();

User::find($id)->descendants()->update(['active' => false]);

User::find($id)->siblings()->delete();

特性提供tree()查询作用域,以从根(s)开始获取所有模型

$tree = User::tree()->get();

过滤器

特性提供查询作用域,以根据模型在树中的位置进行过滤

  • hasChildren():具有子级的模型。
  • hasParent():具有父级的模型。
  • isLeaf():没有子级的模型。
  • isRoot():没有父级的模型。
$noLeaves = User::hasChildren()->get();

$noRoots = User::hasParent()->get();

$leaves = User::isLeaf()->get();

$roots = User::isRoot()->get();

排序

特性提供查询作用域以对模型进行广度优先或深度优先排序

  • breadthFirst():先获取兄弟姐妹,再获取子级。
  • depthFirst():先获取子级,再获取兄弟姐妹。
$tree = User::tree()->breadthFirst()->get();

$descendants = User::find($id)->descendants()->depthFirst()->get();

深度

祖先、后代和树查询的结果包括额外的depth列。

它包含模型相对于查询父级的深度 相对 值。对于后代,深度为正,对于祖先,深度为负

$descendantsAndSelf = User::find($id)->descendantsAndSelf()->depthFirst()->get();

echo $descendantsAndSelf[0]->depth; // 0
echo $descendantsAndSelf[1]->depth; // 1
echo $descendantsAndSelf[2]->depth; // 2

您可以通过覆盖getDepthName()来自定义列名

class User extends Model
{
    use \Paxha\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;

    public function getDepthName()
    {
        return 'depth';
    }
}

您可以使用whereDepth()查询作用域通过模型的相对深度进行过滤

$descendants = User::find($id)->descendants()->whereDepth(2)->get();

$descendants = User::find($id)->descendants()->whereDepth('<', 3)->get();

路径

祖先、后代和树查询的结果包括额外的path列。

它包含从查询父级到模型的唯一键的点分隔路径

$descendantsAndSelf = User::find(1)->descendantsAndSelf()->depthFirst()->get();

echo $descendantsAndSelf[0]->path; // 1
echo $descendantsAndSelf[1]->path; // 1.2
echo $descendantsAndSelf[2]->path; // 1.2.3

您可以通过覆盖相应的方法来自定义列名和分隔符

class User extends Model
{
    use \Paxha\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;

    public function getPathName()
    {
        return 'path';
    }

    public function getPathSeparator()
    {
        return '.';
    }
}

贡献

有关详细信息,请参阅CONTRIBUTINGCODE_OF_CONDUCT