Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

roulette6's avatar

Eloquent query with count of objects in a one-to-many relationship

Hello:

I'm trying to get a collection of objects and I'm having trouble figuring out how to create the query. Here are the relationships:

  • There are items and there are stores
  • Each store has many items
  • Each item has only one store

I want to create a query that fetches all stores and the count of the items they have. In pseudo code, I'd say I want stores with count of items order by store name asc. The outcome of such a query would look something like this:

[

    {
        "id": "1",
        "name": "Garden Gourmet",
        "location": "Bronx, NY 10463",
        "created_at": "2014-08-08 02:39:03",
        "updated_at": "2014-08-08 02:39:03",
        "items": 20
    },
    {
        "id": "2",
        "name": "Frank's Market",
        "location": "New York, NY 10040",
        "created_at": "2014-08-08 02:39:03",
        "updated_at": "2014-08-08 02:39:03",
        "items": 15
    },
    {
        "id": "3",
        "name": "Liberato",
        "location": "New York, NY 10032",
        "created_at": "2014-08-14 01:14:12",
        "updated_at": "2014-08-14 01:14:12",
        "items": 5
    }
]

Any suggestions? I want to refrain from using raw SQL, which would be easy enough for me.

0 likes
7 replies
mikebronner's avatar

You might try something like:

class Store extends \Eloquent
{
    protected $fillable = ['name', 'location'];

    public function items()
    {
        return $this->hasMany('Item');
    }
}

class Item extends \Eloquent
{
    protected $fillable = [];

    public function store()
    {
        return $this->belongsTo('Store');
    }
}

Then wherever you retrieve your records:

$stores = Store::with('items')->all();
foreach ($stores as $store) {
    $itemCount = $store->items()->count();
}

Hopefully that gets you close to something useable. :)

1 like
JeffreyWay's avatar
Level 59

If you're trying to limit the number of DB queries you do, you might try something along the lines of this:

Store::join('items', 'items.store_id', '=', 'stores.id')
    ->groupBy('stores.id')
    ->get(['stores.id', 'stores.name', DB::raw('count(items.id) as items')])
);
9 likes
roulette6's avatar

Thanks, Jeffrey. That did it. I would've never thought of that. The only thing I don't like is that stores with 0 items won't appear on the list, but I remember this being an issue for me in another webapp I made using straight PHP/MySQL.

Mike, I figured I could do something similar, but since I was fetching the list of all items associated with the stores instead of the count, I figured that wouldn't be very efficient.

roulette6's avatar

Great! This solved my issue exactly. Thanks a lot.

sandeepseshadri's avatar

will this solution work in ms-sql? i am getting the following error "invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause".

Please or to participate in this conversation.