1
votes

I have a collection from Laravel Eloquent query. Here grandfathers have many children(fathers), fathers have many children(grandchildren). The returned result is this:

    [
  {
    "grand_father_id": "26",
    "fathers": [
      {
        "father_id": "101",
        "children": [
          {
            "child_id": "77",
            "children_weight": [
              {
                "weight": "30.00",
              }
            ]
          },
          {
            "child_id": "84",
            "children_weight": [
              {
                "weight": "20.00",
              }
            ]
          }
        ]
      },
      {
        "father_id": "102",
        "children": [
          {
            "child_id": "78",
            "children_weight": [
              {
                "weight": "50.00",
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "grand_father_id": "27",
    "fathers": [
      {
        "father_id": "100",
        "children": [
          {
            "child_id": "83",
            "children_weight": [
              {
                "weight": "100.00",
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "grand_father_id": "28",
    "fathers": [
      {
        "father_id": "105",
        "children": [
          {
            "child_id": "81",
            "children_weight": [
              {
                "weight": "80.00",
              }
            ]
          },
          {
            "child_id": "82",
            "children_weight": [
              {
                "weight": "0.00",
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "grand_father_id": "29",
    "fathers": [
      {
        "father_id": "108",
        "children": [
          {
            "child_id": "79",
            "children_weight": [
              {
                "weight": "44.00",
              }
            ]
          },
          {
            "child_id": "80",
            "children_weight": [
              {
                "weight": "56.00",
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "grand_father_id": "30",
    "fathers": [
      {
        "father_id": "107",
        "children": [

        ]
      }
    ]
  }
]

How do I count the total number of all grandchildren of all grandfathers. I can ofcourse use nested loop to count this. But is there any other Laravel Collection method to do this? By the way, the example I gave here with grandfather, father, grandchildren is just an example with pseudo names. The real fields are objectives, actions, success_indicators, success_indicator_weight. The query to obtain the collection is:

return Objective::with([
        'actions' => function($query) {
        $query->select(['action_id', 'action_description', 'objective_id_fk']);
    }, 'actions.successIndicators' => function($query) {
        $query->select('success_indicator_id', 'success_indicator_description', 'action_id_fk');
    }, 'actions.successIndicators.SuccessIndicatorYearWeight' => function($query) {
        $query->select('success_indicator_weight', 'success_indicator_unit', 'success_indicator_id_fk');
    },
])->get()
1

1 Answers

1
votes

There are a load of array_* helper methods for doing a variety of operations on nested arrays but I don't think there is anything that would serve your cause there. You can check for yourself - http://laravel.com/docs/5.0/helpers#arrays

I don't know myself if there is anything built into Collection but you could consider an accessor method of each Grandfather class:

class Grandfather extends Eloquent
{
    ...
    public function getTotalGrandchildrenAttribute()
    {
        $total_grandchildren = 0;
        // loop through each father
        foreach ($this->fathers as $father) {
            $total_grandchildren += count($father->children);
        }
        return $total_grandchildren;
    }
}

Then in your script:

$grandfathers = Grandfathers::all();

$total_grandchildren = 0;
foreach ($grandfathers as $grandfather) {
    $total_grandchildren += $grandfather->total_grandchildren;
}

echo "Total grandchildren: $total_grandchildren";

http://laravel.com/docs/5.0/eloquent#accessors-and-mutators

In addition, instead of using all() as shown above, you may want to use with('fathers') and with('children') so you're not hitting the DB every time you want to fetch fathers/ children:

$grandfathers = Grandfathers::with(array('fathers' => function($query) {
    $query->with('children');
});

http://laravel.com/docs/5.0/eloquent#eager-loading