当前位置: 首页 > 知识库问答 >
问题:

拉威尔递归关系

诸葛茂勋
2023-03-14

我在拉维尔做一个项目。我有一个帐户模型,可以有父帐户,也可以有子帐户,因此我的模型设置如下:

public function immediateChildAccounts()
{
    return $this->hasMany('Account', 'act_parent', 'act_id');
}

public function parentAccount()
{
    return $this->belongsTo('Account', 'act_parent', 'act_id');
}

这工作正常。我想做的是让所有的孩子都在某个账户下。目前,我正在这样做:

public function allChildAccounts()
{
    $childAccounts = $this->immediateChildAccounts;
    if (empty($childAccounts))
        return $childAccounts;

    foreach ($childAccounts as $child)
    {
        $child->load('immediateChildAccounts');
        $childAccounts = $childAccounts->merge($child->allChildAccounts());
    }

    return $childAccounts;
}

这也行得通,但我不得不担心它是否缓慢。这个项目是我们在工作中使用的旧项目的重写。我们将有几千个帐户迁移到这个新项目。对于我拥有的几个测试帐户,这种方法不会带来性能问题。

有没有更好的解决办法?我应该运行一个原始查询吗?Laravel有什么东西可以处理这个吗?

总之,对于任何给定的帐户,我想做的是在单个列表/集合中获取每个子帐户及其子帐户的每个子帐户,以此类推。图表:

A -> B -> D
|--> C -> E
     |--> F 
G -> H

如果我运行一个-

同样,我的方法是有效的,但似乎我做的查询太多了。

另外,我不确定在这里问这个是否合适,但这是相关的。如何获取不包括子帐户的所有帐户的列表?所以基本上与上面的方法相反。这样,用户就不会试图给一个帐户指定一个已经是其子帐户的父帐户。使用上面的图表,我想要(伪代码):

帐户::(account_id不在(A-

谢谢你的任何见解。

共有3个答案

沈乐邦
2023-03-14

我创建了一个使用公共表表达式(CTE)实现递归关系的包:https://github.com/staudenmeir/laravel-adjacency-list

您可以使用子体关系递归获取帐户的所有子项:

class Account extends Model
{
    use \Staudenmeir\LaravelAdjacencyList\Eloquent\HasRecursiveRelationships;
}

$allChildren = Account::find($id)->descendants;
晏富
2023-03-14
public function childrenAccounts()
{
    return $this->hasMany('Account', 'act_parent', 'act_id')->with('childrenAccounts');
}

此代码返回所有子帐户(定期)

张建树
2023-03-14

以下是如何使用递归关系:

public function childrenAccounts()
{
    return $this->hasMany('Account', 'act_parent', 'act_id');
}

public function allChildrenAccounts()
{
    return $this->childrenAccounts()->with('allChildrenAccounts');
}

然后:

$account = Account::with('allChildrenAccounts')->first();

$account->allChildrenAccounts; // collection of recursively loaded children
// each of them having the same collection of children:
$account->allChildrenAccounts->first()->allChildrenAccounts; // .. and so on

这样可以节省大量查询。这将在每个嵌套级别执行1个查询1个附加查询。

我不能保证它对您的数据有效,您需要明确地测试它。

这适用于无子女账户:

public function scopeChildless($q)
{
   $q->has('childrenAccounts', '=', 0);
}

然后:

$childlessAccounts = Account::childless()->get();
 类似资料:
  • 我有一个奇怪的问题。 我有一个用户表和一个公司表。一个用户属于一家公司,而一家公司有许多用户。 表的两个主键都是id。 在laravel文档中,我阅读了以下内容: 此外,Eloquent假设外键的值应该与父项的id列匹配。 我在我的

  • 我的情况是,我有帖子、用户和评论。 每个评论都存储一个post_id和一个user_id。我要做的是获取用户对特定帖子的所有评论,这样我就可以进行如下调用: (我知道x是什么) 我有: 我觉得需要有一个where或have或where have或是什么东西。。我能做的最好的事情就是拉Auth::User()-

  • 是否还要向findForPassport添加或传递1个变量? 在默认的laravel passport登录中,我只能传递2个变量(用户名、密码),但我想再传递1个变量,并在findForPassport中检查该用户是否属于其他表。

  • 我目前正在研究构建SaaS构建管理工具。我想知道的是,如果我使用laravel passport作为api令牌,我如何为用户分配角色,例如: SuperAdmin:可以创建项目|可以创建新用户并为用户分配角色。 管理员:可以查看项目。 因为我希望能够根据用户权限隐藏前端上的元素。 例如,如果我使用传统的laravel应用程序,我可以使用委托和刀片指令@role('admin')来显示基于用户权限类

  • 是否有一种方法可以将范围添加到BelongsTo很多字段,以便在附加相关模型时只能从受限选项中执行此操作? 例子: 发布物品到许多标签(使用Sploe/Laravel-Tags)。标签属性到许多帖子。 标签模型具有id、名称、段塞、类型和时间戳属性。 在细节或更新视图上,我希望能够将标签附加到Post。 使用Post资源上的默认BelongToMany字段(或第三方包),我可以向Post添加标记。

  • 我对拉威尔望远镜的部分有点困惑。 我有一个用户模型和表。 如何为用户分配用户、客户和/或管理员的角色。 我有一个带有vue和laravel api后端的水疗中心。我用https://laravel.com/docs/5.3/passport#consuming-使用javascript创建api 我如何分配哪个用户模型具有哪些作用域? 还是范围与角色不同? 您将如何实现这一点? 提前谢谢!

  • 我对Laravel截断的数据有一个小问题。我将传递给我的后端值,该值可以是表中定义的“百分比”或“金额”,但在表中也可以为null,但每次尝试将其设置为null时,都会出现如下错误: {"discount_currency":["您输入的值无效。"]} 或者当我从处理请求中删除enum时,它会说 所以我传递数据抛出API从我的Vue,这个婴儿车的请求看起来像: 所以如果我删除...我有第二个错误。

  • 我正在构建一个Laravel web应用程序,其中我需要一个动态图像库,我构建了一个后端管理面板,可以在其中添加图像,我成功地将图像添加并保存到数据库中,但我无法编辑或删除它们。 错误是: UrlGenerationException中的ErrorException。php第17行:缺少[Route:galleries.update][URI:backend/galleries/{gallery}