Laravel withCount() returns wrong value

In my application there are users making pictures of items. The relationship structure is as follows:

Categories -> SubCategories -> Items -> Pictures -> Users

Now, there's also a shortcut relationship called itemPics between categories <--> pictures so that the number of pictures uploaded by a user can be quickly counted per category using withCount().

These are the relationships on the Category model:

public function subcategories() 
{
    return $this->hasMany('App\SubCategory');
}

public function items()
{
    return $this->hasManyThrough('App\Item', 'App\SubCategory');
}

public function itemPics()
{
    return $this->hasManyThrough('App\Item', 'App\SubCategory')
    ->join('pictures','items.id','=','pictures.item_id')
    ->select('pictures.*');
}

My problem is getting the number of pictures that a user has gathered per category. The itemPics_count column created by withCount() always has the same value as items_count, even though the number of related models for both relations given by with() are different in the JSON output.


        $authorPics = Category::with(['SubCategories', 'SubCategories.items' => function ($q) use ($author_id) {
                $q->with(['pictures' => function ($q) use ($author_id) {
                    $q->where('user_id', $author_id);
                }]);
            }])
        ->with('itemPics') /* added this to check related models in output */
        ->withCount(['items','itemPics'])
        ->get();
        dd($authorPics);

This does not make sense to me. Any help is greatly appreciated.

Upvotes: 2

Views: 1031

Answers (2)

Bulut
Bulut

Reputation: 155

Withcount() function is not work properly if relations include join. it works only table to table relations.

    public function itemPics()
{
    return $this->hasManyThrough('App\Item', 'App\SubCategory')
    ->select('pictures.*');
}

Upvotes: 1

Roman Grinev
Roman Grinev

Reputation: 1037

This solution was worked for me:

//...
public function itemPics()
{
    return $this->hasManyThrough('App\Item', 'App\SubCategory');
}

Then you can do something like this:

$authorPics = Category::with(['SubCategories', 'SubCategories.items' => function ($q) use ($author_id) {
      $q->with(['pictures' => function ($q) use ($author_id) {
         $q->where('user_id', $author_id);
      }]);
   }])
   ->with('itemPics') /* added this to check related models in output */
   ->withCount(['items','itemPics' => function($query){
      $query->join('pictures','items.id','=','pictures.item_id')
         ->select('pictures.*');
   }])
   ->get();
dd($authorPics);

Link to more information about Laravel withCount function here https://laravel.com/docs/8.x/eloquent-relationships#counting-related-models

Upvotes: 0

Related Questions