rawac41707
rawac41707

Reputation: 143

Laravel with() eager loading returning empty data

I have a one-to-many relationship in my model. Basically a Category and a Product. A product can only have one category but a category can have many products. The code below works:

return Category::select('id', 'name')->whereIn('id', $categories)->with('products')->get();

It returns with a product key and within that the product columns in the database, but when I use eager loading it just returns an empty set:

return Category::select('id', 'name')->whereIn('id', $categories)->with(['products' => function($query){
            $query->limit(5);
        }])->get();

I've also tried adding the return keyword like this return $query->limit(5); but still no luck.

I have also tried specifying columns like this:

return Category::select('id', 'name')->whereIn('id', $categories)->with('products:id,name')->get();

But it still returns an empty dataset.

Since I'm building an API, this is what the JSON data looks like:

[
     {
        "id": 161,
        "name": "Health & Personal Care",
        "products": []
    },
    {
        "id": 256,
        "name": "Makeup & Fragrances",
        "products": []
    },
]

My table structure:

categories (there's no product_id column, since it's one to many)
+----+------+
| id | name |
+----+------+
|    |      |
+----+------+
|    |      |
+----+------+
|    |      |
+----+------+

product
+----+------+-------+-------------+
| id | name | price | category_id |
+----+------+-------+-------------+
|    |      |       |             |
+----+------+-------+-------------+
|    |      |       |             |
+----+------+-------+-------------+
|    |      |       |             |
+----+------+-------+-------------+

My category model is declared like this:

public function products()
{
    return $this->hasMany(Product::class);
}

and the product model is:

public function category()
{
     return $this->belongsTo(Category::class);
}

Upvotes: 1

Views: 810

Answers (1)

OMR
OMR

Reputation: 12218

you are trying to limit the loaded relation, not the query, you can do this using eloquent-eager-limit

install it:

composer require staudenmeir/eloquent-eager-limit:"^1.0"

then in Category Model:

class Category extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
.....
public function products()
{
return $this->hasMany(Product::class, 'product_id');
}

public function lastFiveProducts()
{
return $this->hasMany(Product::class, 'product_id')
->latest()->limit(5);
}
    }

and in Product:

class Product extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
......
}

now this query will get the expected results:

return Category::select('id', 'name')->whereIn('id', $categories)->with(['products' => function($query){
            $query->limit(5);
        }])->get();

or using the new relation:

  return Category::select('id', 'name')->whereIn('id', $categories)->with(['lastFiveProducts'])->get();

also note when you use ->with('products:id,name') loading a relation with specific columns, you always should load the foreing key ->with('products:id,name,category_id')

Upvotes: 1

Related Questions