Reputation: 429
We have two classes: Module and Resource, with a module having many resources:
class Module extends Model {
public function resources() {
return $this->hasMany('App\Models\Resource');
}
}
and a resource belonging to a Module:
class Resource extends Model {
public function module() {
return $this->belongsTo('App\Models\Module');
}
}
I need to show a list of all the modules with:
The first one is added to the Module model so it can be used with eager loading:
public function resourcesCount() {
return $this->hasMany('App\Models\Resource')
->selectRaw('module_id, count(*) AS aggregate')
->groupBy('module_id');
}
However, I can't find an efficient and elegant way to calculate the average of the counts calculated by resourcesCount. I know I could iterate through the results of
$modules = Module::with('resourcesCount')->get();
and do it manually, but I feel there's something better out there.
EDIT: forgot to say that I modified the accessor for the resourcesCountAttribute:
public function getResourcesCountAttribute() {
if (!$this->relationLoaded('resourcesCount'))
$this->load('resourcesCount');
$related = $this->getRelation('resourcesCount');
return ($related) ? (int) $related->aggregate : 0;
}
So I can use 'resourcesCount' (See my response), rather than having to use 'resourcesCount.aggregate'.
Upvotes: 1
Views: 1820
Reputation: 429
I found out an acceptable way to do so, using the collection's methods.
// Returns an elloquent collection
$modules = Module::with('resourcesCount')->get();
// counts sums divided by the number of
$avgResources = $modules->sum('resourcesCount') / $modules->count();
Upvotes: 1
Reputation: 171
The only way would be to do it through iteration or in a separate DB::select() statement, relying on things like GROUP BY and AVERAGE().
Upvotes: 0