Laravel Eloquent how to get all products according to category id

Viewed 8777

UserProductsController

class UserProductsController extends Controller
{
    public function index()
    {
        $products = Product::get();
        return view ('products')->with(compact('products'));
      
    }
      
    public function product_categories()
    {
        $categories = Category::all();
        return view ('categories')->with(compact('categories'));
      
    }
  
}

products_table

 public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('prod_name');
            $table->string('prod_brand')->nullable();
            $table->unsignedBigInteger('cat_id');
            $table->string('prod_image_path')->nullable();
            $table->timestamps();

            $table->foreign('cat_id')
            ->references('id')
            ->on('categories')
            ->onDelete('cascade');
        });
    }

categories_table

   public function up()
        {
            Schema::create('categories', function (Blueprint $table) {
                $table->bigIncrements('id');
                $table->string('cat_name');
                $table->string('cat_image_path')->nullable();
                $table->string('cat_description')->nullable();
                $table->timestamps();
            });
        }

Product Model

class Product extends Model
{
  

    public function category()
    {
        return $this->belongsTo('App\Category','category_id');
    }
 
    
}

Category Model

class Category extends Model
{
   public function category()
   {
       return $this->hasMany('App\Product');
   }
}

My route is

Route::get('/All_Products', 'UserProductsController@index')->name('All_Products');
Route::get('/product_categories', 'UserProductsController@product_categories')->name('categories');

How can I get all products with the same category? As this is my first project I am spending much more time on this. But nothing worked for me. Can anyone guide me, please?

4 Answers

Assuming you setup your relationships correctly (which they are not)

You have a few ways with Eloquent:

$products = Category::findOrFail($categoryId)->products;

$products = Product::where('category_id', $categoryId)->get();

$products = Product::whereHas('category', function ($query) use ($categoryId) {
    $q->where('id', $categoryId);
})->get();

To list a few.

Laravel 7.x Docs - Eloquent - Retrieving Single Models / Aggregates findOrFail

Laravel 7.x Docs - Eloquent - Relationships - Relationship Methods vs Dynamic Properties

Laravel 7.x Docs - Eloquent - Relationships - Querying the Existence of Relationships whereHas

First of all, you have not defined your relationships correctly. It should be something like this:

class Product extends Model
{
    public function category()
    {
        return $this->belongsTo('App\Category');
    }
}
class Category extends Model
{
   public function products()
   {
       return $this->hasMany('App\Product');
   }
}

Then in your products migration file, cat_id should be renamed to category_id. That way, you don't need to specify the foreign key on the relationship.

I assume you want to list all the products that belong to a particular category. You can easily do that with the route model binding. In which case your route should look something like:

Route::get('categories/{category:id}/products', [CategoryController::class, 'products']);

And then in your controller:

use App\Category;

class CategoryController extends Controller
{
    public function products(Category $category)
    {
        $category->load('products');

        return view('products')->withCategory($category);
    } 
}

You can access the list of products in your blade view like so: $category->products

You need to make an adjustment to your Category model as a Category has many Products. As it stands, the naming of the relationship doesn't reflect that

class Category extends Model
{
   public function products()
   {
       return $this->hasMany('App\Product');
   }
}

You can then access the products via the Category model like so.

$categories = Category::with('products')->all();

$categories->each(function($category) {
    $products = $category->products;
    
    // Dump & Die a collection of products
    dd($products);
});

Note: I have eager loaded the relationship using the with() method, this is just to prevent n+1 queries. More information on eager and lazy loading can be found on the documentation.

You can do something like,

$products = product::with('categories')->get();
foreach($products as $product)
{
    foreach($product->categories as $category)
    {
        echo $category->name;
    }
}
$categories = Category::with('products')->get();

$category = Category::with('products')->find($category_id);
Related