Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Laravel-获取树结构中的计数,其中父级中的计数是来自子级的计数之和_Php_Laravel_Count_Tree_Relationships - Fatal编程技术网

Php Laravel-获取树结构中的计数,其中父级中的计数是来自子级的计数之和

Php Laravel-获取树结构中的计数,其中父级中的计数是来自子级的计数之和,php,laravel,count,tree,relationships,Php,Laravel,Count,Tree,Relationships,我在这个问题上挣扎了一段时间,找不到解决办法,所以我希望能帮上忙 我有两个相关的模型,ModelOne,它也与自身相关,可以有无限多的子代、孙辈等,并且与ModelTwo相关 class ModelOne extends Model { ... public function model_two() { return $this->hasMany(ModelTwo::class, 'foreign_key'); } //recur

我在这个问题上挣扎了一段时间,找不到解决办法,所以我希望能帮上忙

我有两个相关的模型,
ModelOne
,它也与自身相关,可以有无限多的子代、孙辈等,并且与
ModelTwo
相关

class ModelOne extends Model
{
    ...

    public function model_two()
    {
        return $this->hasMany(ModelTwo::class, 'foreign_key');
    }

    //recursively get all children, grandchildren etc.
    public function children() {
        return $this->hasMany(ModelOne::class, 'foreign_key')->with('children');
    }

    public function parent() {
        return $this->belongsTo(ModelOne::class, 'foreign_key');
    }
}

class ModelTwo extends Model
{
    ...

    public function model_one()
    {
        return $this->belongsTo(ModelOne::class, 'foreign_key');
    }   
}
在我从
ModelOne
获取函数中,我有:

public function get($id = null) {
    return is_null($id) ?
        ModelOne::withCount('model_two')->get() :
        ModelOne::withCount('model_two')->where('id', $id)->first();
}
这给了我一个很好的一维对象数组(或一个对象),带有计数形式相关的
ModelTwo
,这是我需要的,但是每个相关对象都有单独的计数

我需要的是,对于返回数组中具有子对象、孙子对象等的每个
ModelOne
对象,在该对象中计数是其所有子对象、孙子对象等的计数之和。 例如,如果我有一个id=2的
ModelOne
对象,父对象id=1,计数为3,另一个对象id=3,父对象id=1,计数为2,那么对于id=1的对象,即前两个对象的父对象,计数为5。对于所有节点,此逻辑在树中继续向上

[
  {
    "id":1
    "parent_id":"NULL",
    "model_two_count":5
  },
  {
    "id":2
    "parent_id":1,
    "model_two_count":3
  },
  {
    "id":3
    "parent_id":1,
    "model_two_count":2
 }

 ...

]
[
  {
    "id":1
    "parent_id":"NULL",
    "model_two_count":5
  },
  {
    "id":2
    "parent_id":1,
    "model_two_count":3
  },
  {
    "id":3
    "parent_id":1,
    "model_two_count":2
 }

 ...

]

所以,我找到了解决办法,这是给你们所有可能在同一个问题上挣扎的人的

首先,在我的
ModelOne
中,我添加了
withCount('model_two')
,这样我可以立即从
ModelOne
中获得关系计数。我还添加了一个属性
$return\u count
,它将保存所有子孙辈的计数总和

class ModelOne extends Model
{

    private $return_count = 0;

    ...

    public function model_two()
    {
        return $this->hasMany(ModelTwo::class, 'foreign_key');
    }

    //recursively get all children, grandchildren etc.
    public function children() {
        return $this->hasMany(ModelOne::class, 'foreign_key')->withCount('model_two')->with('children');
    }

    public function parent() {
        return $this->belongsTo(ModelOne::class, 'foreign_key');
    }
}
然后,我添加了两个helper函数,一个递归获取给定父id的所有子孙辈等,或者返回表中的所有记录:

public function get_recursive($parentId = null){
    return is_null($parentId) ?
        ModelOne::with('children')->get() :
        ModelOne::where('id', $parentId)->with('children')->first();
}
此函数的输出如下所示:

[
  {
    "id":1
    "parent_id":"NULL",
    "model_two_count":0.
    "children": [
        {
            "id":2
            "parent_id":1,
            "model_two_count":3
        },
        {
            "id":3
            "parent_id":1,
            "model_two_count":2
         }
      ]
   }

 ...

]
此示例适用于二维嵌套,但可以无限深入。 在此函数中创建的返回对象将成为第二个函数中的输入参数。第二个函数实际上是对给定父对象的所有子对象、孙子对象等的计数进行递归求和。可以访问属性
model\u two\u count
,因为它是在调用
withCount('model\u two')
时创建的。另外,当调用带有('children')的
时,将创建属性
子对象

private function count_sum($parentChildren) {
    foreach ($parentChildren->children as $child) {
        $this->return_count += $child->model_two_count;
        $this->count_sum($child);
    }
    return $this->return_count;
}
最后,我调用get函数:

public function get($id = null) {
    if(is_null($id = null)) {
        $data = ModelOne::withCount('model_two')->get();                 
        return $data->map(function ($i) {               

            //get all children-grandchildren-etc. for specfic object with id = $i->id
            $children = $this->get_recursive($i->id);

             //if object with id = $i->id have children then model_two_count is sum of all model_two_count from all children-grandchildren-etc.                    
             if (!empty(array_filter((array)$children->children))) {
                $i->model_two_count = $this->count_sum($children);
                //reset the return_count variable for next iteration. If this is not done, then sum from previous object will be added to the next object count
                $this->return_count = 0;
            } 
            return $i;
        });
    } else {
        $data = ModelOne::withCount('model_two')->where('id', $id)->get();                 
        return $data->map(function ($i) {
            $children = $this->get_recursive($i->id);
            if (!empty(array_filter((array)$children->children))) {
                $i->model_two_count = $this->count_sum($children);                         
                $this->return_count = 0;
             } 
             return $i;
         })->first();
     }
 }
这将获得您想要的良好输出:


所以,我找到了解决办法,这是给你们所有可能在同一个问题上挣扎的人的

首先,在我的
ModelOne
中,我添加了
withCount('model_two')
,这样我可以立即从
ModelOne
中获得关系计数。我还添加了一个属性
$return\u count
,它将保存所有子孙辈的计数总和

class ModelOne extends Model
{

    private $return_count = 0;

    ...

    public function model_two()
    {
        return $this->hasMany(ModelTwo::class, 'foreign_key');
    }

    //recursively get all children, grandchildren etc.
    public function children() {
        return $this->hasMany(ModelOne::class, 'foreign_key')->withCount('model_two')->with('children');
    }

    public function parent() {
        return $this->belongsTo(ModelOne::class, 'foreign_key');
    }
}
然后,我添加了两个helper函数,一个递归获取给定父id的所有子孙辈等,或者返回表中的所有记录:

public function get_recursive($parentId = null){
    return is_null($parentId) ?
        ModelOne::with('children')->get() :
        ModelOne::where('id', $parentId)->with('children')->first();
}
此函数的输出如下所示:

[
  {
    "id":1
    "parent_id":"NULL",
    "model_two_count":0.
    "children": [
        {
            "id":2
            "parent_id":1,
            "model_two_count":3
        },
        {
            "id":3
            "parent_id":1,
            "model_two_count":2
         }
      ]
   }

 ...

]
此示例适用于二维嵌套,但可以无限深入。 在此函数中创建的返回对象将成为第二个函数中的输入参数。第二个函数实际上是对给定父对象的所有子对象、孙子对象等的计数进行递归求和。可以访问属性
model\u two\u count
,因为它是在调用
withCount('model\u two')
时创建的。另外,当调用带有('children')
时,将创建属性
子对象

private function count_sum($parentChildren) {
    foreach ($parentChildren->children as $child) {
        $this->return_count += $child->model_two_count;
        $this->count_sum($child);
    }
    return $this->return_count;
}
最后,我调用get函数:

public function get($id = null) {
    if(is_null($id = null)) {
        $data = ModelOne::withCount('model_two')->get();                 
        return $data->map(function ($i) {               

            //get all children-grandchildren-etc. for specfic object with id = $i->id
            $children = $this->get_recursive($i->id);

             //if object with id = $i->id have children then model_two_count is sum of all model_two_count from all children-grandchildren-etc.                    
             if (!empty(array_filter((array)$children->children))) {
                $i->model_two_count = $this->count_sum($children);
                //reset the return_count variable for next iteration. If this is not done, then sum from previous object will be added to the next object count
                $this->return_count = 0;
            } 
            return $i;
        });
    } else {
        $data = ModelOne::withCount('model_two')->where('id', $id)->get();                 
        return $data->map(function ($i) {
            $children = $this->get_recursive($i->id);
            if (!empty(array_filter((array)$children->children))) {
                $i->model_two_count = $this->count_sum($children);                         
                $this->return_count = 0;
             } 
             return $i;
         })->first();
     }
 }
这将获得您想要的良好输出: