Laravel 递归关系 [英] Laravel Recursive Relationships

查看:57
本文介绍了Laravel 递归关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 Laravel 中开展一个项目.我有一个可以有父级或可以有子级的帐户模型,所以我的模型设置如下:

I'm working on a project in Laravel. I have an Account model that can have a parent or can have children, so I have my model set up like so:

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

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

这很好用.我想要做的是让所有孩子都在某个帐户下.目前,我正在这样做:

This works fine. What I want to do is get all children under a certain account. Currently, I'm doing this:

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;
}

这也有效,但我不得不担心它是否很慢.这个项目是我们在工作中使用的一个旧项目的重写.我们将有数千个帐户迁移到这个新项目.对于我拥有的少数测试帐户,这种方法不会造成性能问题.

This also works, but I have to worry if it's slow. This project is the re-write of an old project we use at work. We will have several thousand accounts that we migrate over to this new project. For the few test accounts I have, this method poses no performance issues.

有更好的解决方案吗?我应该只运行原始查询吗?Laravel 有办法处理这个问题吗?

Is there a better solution? Should I just run a raw query? Does Laravel have something to handle this?

总结对于任何给定的帐户,我想要做的是在单个列表/集合中获取每个子帐户及其子项的每个子项等等.一张图:

In summary What I want to do, for any given account, is get every single child account and every child of it's children and so on in a single list/collection. A diagram:

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

如果我运行 A->immediateChildAccounts(),我应该得到 {B, C}
如果我运行 A->allChildAccounts(),我应该得到 {B, D, C, E, F}(顺序无关紧要)

If I run A->immediateChildAccounts(), I should get {B, C}
If I run A->allChildAccounts(), I should get {B, D, C, E, F} (order doesn't matter)

同样,我的方法有效,但似乎我进行了太多查询.

Again, my method works, but it seems like I'm doing way too many queries.

另外,我不确定在这里问这个问题是否可以,但它是相关的.如何获取包括子帐户的所有帐户的列表?所以基本上与上述方法相反.这样用户就不会尝试将已经是其孩子的父母提供给帐户.使用上面的图表,我想要(在伪代码中):

Also, I'm not sure if it's okay to ask this here, but it is related. How can I get a list of all accounts that don't include the child accounts? So basically the inverse of that method above. This is so a user doesn't try to give an account a parent that's already it's child. Using the diagram from above, I want (in pseudocode):

Account::where(account_id 不在 (A->allChildAccounts())) 中.所以我会得到 {G, H}

Account::where(account_id not in (A->allChildAccounts())). So I would get {G, H}

感谢您的任何见解.

推荐答案

这是如何使用递归关系:

This is how you can use recursive relations:

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 个附加查询.

This way you save a lot of queries. This will execute 1 query per each nesting level + 1 additional query.

我不能保证它对您的数据有效,您需要绝对测试.

I can't guarantee it will be efficient for your data, you need to test it definitely.

这适用于无子女帐户:

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

然后:

$childlessAccounts = Account::childless()->get();

这篇关于Laravel 递归关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆