2

Reuqirment

My DB has a table named categories and also a table named products where products table has a row named category_id which make the relationship with categories table. So I wants to show random 7 categories from my categories table and also I needs to show 6 products from each category too.

Framework

Laravel 5.3

What I have done

  • To fetch 8 random categories

    This code work as I wants so no issue with this code segment

     $masterCategoryList = Category::where('parent_id', 0)
                                      ->where('id', '!=',0)
                                      ->inRandomOrder()
                                      ->take(8)
                                      ->get();
    
  • Fetch 6 random products for each selected random Master Category List id $masterCategoryList So what I have done is

    $productsMatcheToMasterCategory = []; 
    
             for($a = 0; $a<8; $a++){
    
       $productsMatcheToMasterCategory =
                               Product::where('category_id',$masterCategoryList[$a]['id'])    
                               ->inRandomOrder()
                               ->take(6)
                               ->get();    
     }
    

But this only output 6 products which related one category when I use dd($productsMatcheToMasterCategory)after the loop.Like below

 Category 01

       - Product 01

       - Product 02

My expected out put is something like below

Category 01
           - Product 01
           - Product 02
Category 02
           - Product 01
           - Product 02

Could anyone please tell me why does this happen.

Thanks

2 Answers 2

3

This is because you are just replacing the value inside the array. It is just creating the array with index 0.

$productsMatcheToMasterCategory = []; 
for($a = 0; $a<8; $a++){
$output =
Product::where('category_id',$masterCategoryList[$a]['id'])    
         ->inRandomOrder()
         ->take(6)
         ->get();    
array_push($productsMatcheToMasterCategory, $output)
}
Sign up to request clarification or add additional context in comments.

1 Comment

please rename function arry to array. Thanks
2

In the way you are doing it, you are overriding the value you previously assigned to the variable. To avoid that, add an empty pair of brackets to the variable to indicate that you assign each result of each query in the loop to a new element in the array.

$masterCategoryList = Category::where('parent_id', 0)
                                ->where('id', '!=',0)
                                ->inRandomOrder()
                                ->take(8)
                                ->get();

$productsMatcheToMasterCategory = []; 

for($a = 0; $a < 8; $a ++) {
    // here note the $productsMatcheToMasterCategory [] = ...
    $productsMatcheToMasterCategory [] = Product::where('category_id',$masterCategoryList[$a]['id'])    
                                                ->inRandomOrder()
                                                ->take(6)
                                                ->get();    
}

but in that way you have 9 queries, 1 to get the eight categories and 8 to get the products for each category.

Another approach I can think of is by defining the relationships in the models:

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



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

and getting the related products by the method with() constraining the eager loads, wich results in just one query:

$collection = Category::where('parent_id', 0)
            ->where('id', '!=',0)
            ->inRandomOrder()
            ->take(8)
            ->with([
                'products' => function($query) {
                    $query->inRandomOrder()
                          ->take(6);
                },
            ])
            ->get();
$array = $collection->toArray();

1 Comment

Thanks for this well explained answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.