In the home page, I display categories with the products. There are 3 tables in the database that comes into play in home page 'section control', 'categories' and 'products'. The 'section control' table has section name and the category_id they are associated with. The 'categories' table stores the name of the category and parent_id which is the id of the parent category (that is selected from the lists in 'categories' table itself. Means a single table for parent and child category) and the 'products' table has product details and category_id.
Now, when i select a category using section control (backend), it displays products from that category only. If the category selected further has other child categories, it doesn't render the products on those child categories.
Section Control model:
class SectionControl extends Model
{
protected $table = "section_control";
protected $fillable = [
'name', 'display_name', 'details', 'status', 'has_category', 'category_id'
];
public function category() {
return $this->belongsTo('App\Models\Category', 'category_id')->with('children');
}
public function products() {
return $this->category->hasMany('App\Models\Product', 'category_id');
}
}
Category Model:
class Category extends Model
{
protected $table = 'categories';
public function getRouteKeyName() {
return 'slug';
}
public function children()
{
return $this->hasMany('App\Models\Category', 'parent_id');
}
// recursive, loads all descendants
public function childrenRecursive()
{
return $this->children()->with('childrenRecursive');
// which is equivalent to:
// return $this->hasMany('Survey', 'parent')->with('childrenRecursive);
}
// parent
public function parentCategory()
{
return $this->belongsTo('App\Models\Category','parent_id');
}
// all ascendants
public function parentRecursive()
{
return $this->parentCategory()->with('parentRecursive');
}
public function products() {
return $this->hasMany('App\Models\Product', 'category_id');
}
public function childrenRecursiveIds() {
return $this->childrenRecursive()->pluck('id');
}
public function productsRecursive() {
$products = \App\Models\Product::whereIn('category_id', $category_ids)->get();
return $products;
}
}
Product Model:
class Product extends Model
{
protected $table = 'products';
public function getRouteKeyName() {
return 'slug';
}
public function category() {
return $this->belongsTo('App\Models\Category', 'category_id');
}
public function deals_of_the_week() {
return $this->hasOne('App\Models\DealOfTheWeek', 'product_id');
}
}
And the getIndex function in the controller is:
public function getIndex()
{
$section_control = SectionControl::with('category')->get()->keyBy('id');
$section = [
'section_control_slider' => $section_control[1],
'section_control_deals' => $section_control[2],
'section_control_category_1' => $section_control[3],
];
$data['main_sliders'] = MainSlider::where('status', 1)->orderBy('created_at', 'desc')->get();
$data['deals_of_the_week'] = DealOfTheWeek::with('product')->orderBy('created_at', 'desc')->limit('20')->get();
$data['category_1_products'] = $section['section_control_category_1']->products()->with('images')->limit(18)->orderBy('created_at', 'desc')->get();
return view('frontend.home.index')
->with($section)
->with($data);
}
UPDATE I tried both way by addind the macro in the boot function of AppServiceProvider and in construct funtion in SectionContol Model. None of them worked. Maybe i lack the basics.
public function boot()
{
Builder::macro('recursive', function () {
return $this->children->map(function (Category $category) {
if ($category->children->count()) {
return $category->children->each->recursive();
}
return $category->products;
});
});
}
In Controller
public function getIndex() {
$section_control = SectionControl::with('category')->get()->keyBy('id');
$section = [
'section_control_slider' => $section_control[1],
'section_control_deals' => $section_control[2],
'section_control_category_1' => $section_control[3],
'section_control_category_2' => $section_control[4],
'section_control_featured' => $section_control[5],
'section_control_category_3' => $section_control[6],
'section_control_category_4' => $section_control[7],
'section_control_category_5' => $section_control[8],
'section_control_partners' => $section_control[9],
];
$data['category_3_products'] = $section_control[4]->category->recursive();
return response()->json($data);
}
I would like to explain the scenario again. I am assigning a category to a section. The parent category has a unique category_id and parent_id is null. the subcategories have their own category_id and parent_id that of their parent. There is single table categories for both parent and children. In products table, product are assigned only category_id. if the category assigned to the section is a child, the originally posted code does the trick. But id the category is parent, it doesn't show anything.
Above, I forgot to add SectionControl model. Here it is.
class SectionControl extends Model
{
protected $table = "section_control";
protected $fillable = [
'name', 'display_name', 'details', 'status', 'has_category', 'category_id'
];
public function category() {
return $this->belongsTo('App\Models\Category', 'category_id')->with('children');
}
public function products() {
return $this->category->hasMany('App\Models\Product', 'category_id');
}
}