so I have a 5 tables in my database with pivot, Countries, Cities, Shops, Users, shop_employee
their relationship is this
Countries | Cities | Shops | shop_employees| Users
id | country_id | city_id | shop_id | id
employee_id
my goal is I want to count each City, shop, employees in the Country
this is my controller
class CountryController extends Controller
{
public function country(){
$countries = Country::with(['cities.shops.employees'])->get();
return view('country',['countries'=>$countries]);
}
}
this is my model Country
class Country extends Model
{
public function cities(){
return $this->hasMany(City::class);
}
}
this is my model City
class City extends Model
{
public function shops(){
return $this->hasMany(Shop::class);
}
}
this is my model Shops
class Shop extends Model
{
public function employees(){
return $this->belongsToMany(User::class,'shop_employees','shop_id','employee_id');
}
}
this is my view
<table >
<thead>
<tr>
<th >Country</th>
<th >City</th>
<th >Shop</th>
</tr>
</thead>
<tbody>
@foreach ($countries as $country)
<tr >
<td >{{ $country->name }}</td>
<td >{{ $country->cities->count() }}</td>
<td ></td>
</tr>
@endforeach
</tbody>
</table>
I tried this code its working fine the City is counting
{{ $country->cities->count() }}
the output, in this output I want to display the count of shops and employee
but when im trying this code it gives me a error
$country->cities->shops->count() or
$country->cities->shops->employees->count()
error: Property [shops] does not exist on this collection instance
CodePudding user response:
You can try to get the aggregate with the query itself
class CountryController extends Controller
{
public function country(){
$countries = Country::with([
'cities' => fn($query) => $query->withCount('shops'),
'cities.shops' => fn($query) => $query->withCount('employees'),
'cities.shops.employees'
])
->withCount('cities')
->get();
return view('country',['countries'=>$countries]);
}
}
Then you can access the aggregate values as
//Get the count of cities under the country
$country->cities_count;
foreach($countries as $country) {
$noOfCities = $country->cities_count;
$noOfShops = $country->cities->sum('shops_count');
$noOfEmployees = $country->cities->reduce(
fn($carry, $city) => $carry $city->shops->sum('employees_count')
);
}
Laravel Docs - Eloquent Relationships - Aggregating Related Models
CodePudding user response:
You can achieve this by using the addSelect
method
Using subquery and passing a closure
Country::withCount('cities as city_count')
->addSelect([
'shop_count' => Shop::selectRaw('count(*)')
->whereIn(
'city_id',
City::select('id')->whereColumn('country_id','countries.id'))
->limit(1),
])
->addSelect([
'employee_count' => DB::table('shop_employees')->selectRaw('count(*)')
->whereIn(
'shop_id',
Shop::select('id')
->whereIn(
'city_id',
City::select('id')->whereColumn('country_id','countries.id')
)
)->limit(1),
])
->get();