Laravel 5递归函数多对多自引用模型

时间:2016-06-08 17:32:13

标签: php mysql laravel recursion laravel-5

我有一个名为Product的模型,它具有以下自引用多对多关系:

// parent products based on the product_product pivot table
public function parent_products()
{
    return $this->belongsToMany('App\Product', 'product_product', 'child_id', 'parent_id')->withPivot('amount');
}

// child products based on the product_product pivot table
public function child_products()
{
    return $this->belongsToMany('App\Product', 'product_product', 'parent_id', 'child_id')->withPivot('amount');
}

// movements
public function movements()
{
    return $this->hasMany('App\Movement', 'product_id');
}

所以任何产品都可以有理想的#34;无限的祖先和孩子。

此外,任何产品都是其他产品的组合,因为它们就像"组件"。

所以我需要返回"可制作的"产品取决于每个孩子的可用性及其构建产品所需的金额。

没有问题,如果这是一个深度的事情,但系统应该让你有很多深度水平,所以任何孩子也可以由孩子制作。

我无法控制每种产品的深度 - >产品 - >产品链。

除了表演问题之外,我还需要一种递归方式来返回"可制作的"链中每种产品的数量。

我设法如何递送孩子直到链的末端,如此

public function child_products_recursive()
{
  return $this->child_products()->with(['child_products_recursive','movements'=>function($query){
    $query->whereDate('ready_date', '<=', date('Y-m-d'))->sum('amount');
  }]);
}

它有效。

但无法弄清楚如何从中返回值或如何导航每个模型。

参与的表格是&#34;简化的&#34;那样:

products
---------
id | name
---------
1  | something
2  | something
3  | something
4  | something
5  | something
6  | something
7  | something


product_product
-----------------------------
parent_id | child_id | amount (amount of children in the parent product)
-----------------------------
1         | 2        | 2
1         | 3        | 4
2         | 4        | 1.5
2         | 5        | 3
4         | 6        | 0.7
4         | 7        | 0.3


movements table
-------------------------------------
id | product_id | date       | amount
-------------------------------------
1  | 4          | 2016-01-06 | 300
2  | 5          | 2016-01-06 | 200
3  | 6          | 2016-01-06 | 125
4  | 7          | 2016-01-06 | 1000

所以产品ID 1没有动作,但可以根据没有动作但也可以由儿童产品构建的儿童产品构建多件。

这里是视觉表现(我之前没有按照表格的数据,只是为了提出这个想法):

            Wine box        Wine box
            6 bottles       12 bottles ---1x-- Box for
            of Wine3        of Wine4           12 Bottles
               /  \             |   \          
              /    \            |    \
            x6      x1          |     x12
            /        \          |      \
         Bottle      Box for    |     Bottle
         of Wine3    6 Bottles  |     Label
         /  |  \                |        
        /   |   \              / \    
       /    |    \            /   \
      /     |     \          /     \
    x1    x0.75    x1      x12      x9
    /       |       \      /         \
Empty       |        Bottle         Wine4
Bottle XY   |        Cork ABC
            |        
            |        
            |
            |
          Wine3
         /    \
        /      \
     x0.7      x0.3
      /          \
   Wine1        Wine2

提前致谢。 侨

1 个答案:

答案 0 :(得分:0)

我不知道我是否明白这个想法,但要测试产品是否 isProducible 我建议如下:

class MyActivityDelegate<T : MvpView>(private val activity: Activity) 
: ActivityMvpDelegate<MvpView, MvpPresenter<T>>

如果产品具有移动,那么它已经存在,否则检查子项,如果 isProducible 检查金额,如果没有任何儿童返回错误;

让我再试一次:

public function getIsProducibleAttribute()
{
    if($this->movements > 0)
        return true;
    else{
        foreach($this->child_products_recursive as $child)
        {
            if(!$child->is_producible)
                return false;

            if($child->movements < $child->pivot->amount)
                return false;
        }

        return true;
    }

}

因此,我检查了儿童的存量和可生产数量,并除以父母制造单位所需的数量。获得最低值,例如:

我有24瓶,但只有一盒12,所以答案是1。

PS。:别忘了绕或不;)