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

ComputerMaverick's avatar

Eloquent Query for array

I have a table structure as defined below

id		code		name			parent_id
1		oj8h4rd		Parent Category 1		0		
2		hg64g3		Sub Category 1		1
3		hwfhjf47	Parent Category N		0
4		kffh4jhw	Parent Category O		0
5		jhs4g3g3	Sub Category 2		3
6		hf373g53	Sub Category 3		3

How do i write an eloquent query do show sub categories of belonging to a particular parent category. e.g Parent category 1 has Sub Category 1

0 likes
14 replies
MichalOravec's avatar
Level 75

Category model

public function children()
{
    return $this->hasMany(Category::class, 'parent_id');
}

public function parent()
{
    return $this->belongsTo(Category::class, 'parent_id');
}

In controller

$category = Category::with('children')->first();

In view

{{ $category->name }} has {{ $category->children->first()->name }}

// but better to use loop

@foreach ($category->children as $subCategory)
    {{ $subCategory->name }}
@endforeach
ComputerMaverick's avatar

Thanks for the help. However, i'd love it if you could explain the inner workings of this query, finally, the query returns that the subcategory belongs to all parent category, rather than just the one for which the parent_id is specified.

That is, I have Cars, Bikes, Bicycle as parent categories, I have just a Toyota belonging to Cars Category, however it Toyota shows as subcategory for Bikes, Bicycles as well.

mkshingrakhiya's avatar

You need to implement many to many relationship with the self to achieve what you want.

ComputerMaverick's avatar

How so sir, a subcategory can only belong to one parent category. That's the implementation as per my use case

mkshingrakhiya's avatar

It might be because of the 0s you stored as a default value for parent_id column. Answer by @michaloravec seems good to me. It should work.

ComputerMaverick's avatar

@michaloravec i have done as suggested however i'm only able to access the child categories. I would like that it shows the parent category as and optgroup element and then the subcategories as options under it.

That is

----->Parent Category Name
	->Subcategory 1
	->Subcategory 2 etc
MichalOravec's avatar

@computermaverick

$categories = Category::with(['children' => function ($query) {
    $query->orderBy('name');
}])->whereNull('parent_id')->orderBy('name')->get();
<select name="category_id">
    @foreach ($categories as $category)
        <optgroup label="{{ $category->name }}">
            @foreach ($category->children as $subCategory)
                <option value="{{ $subCategory->id }}">
                    {{ $subCategory->name }}
                </option>
            @endforeach
        </optgroup>
    @endforeach
</select>
ComputerMaverick's avatar

Thanks Michael, i should have thought of that. However, i still have errors. Please find below the complete codes

Category Model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'code', 'name','parent_id', 'slug', 'thumbnail',
     ];

     public function children()
    {
        return $this->hasMany(Category::class, 'parent');
    }

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

}

Controller Logic

<?php

namespace App\Http\Controllers\Admin;
use App\Category;

use App\Http\Controllers\Controller;
use Cocur\Slugify\Slugify;
use Illuminate\Http\Request;

class CategoryController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $categories = Category::with('children')->whereNull('parent_id')->orderBy('name', 'ASC')->get();
        return view('categories')->with('categories', $categories);
    }

Blade Template

<div class="row">
            @if(!empty($categories))
                @foreach($categories as $category)
                <div class="col-sm-12 col-lg-6 col-xl-4">
                    <div class="card card-img-holder">
                        <div class="card-body list-icons">
                            <div class="clearfix">
                                <img src="{{asset('images/categoryThumbnails/'.$category->thumbnail)}}" alt="{{ $category->name }}" title="{{ $category->name }}" width="400" height="255">
                                <h4>{{ $category->name }}</h4>
                            </div>
                            <div class="card-footer p-0">
                                @foreach($categories->children as $subcategory)
                                <p class="text-muted mb-0 pt-4">{{ $subcategory->name }}</p>
                                @endforeach
                            </div>
                        </div>
                    </div>
                </div>
                @endforeach
            @else
                <h4>No Categories Added Yet.</h4>
            @endif
        </div>

Despite all these i still get the

Property [children] does not exist on this collection instance. (View: /Applications/XAMPP/xamppfiles/htdocs/demoProject/resources/views/categories.blade.php)
MichalOravec's avatar

Here I mentioned how your relationships have to look like.

public function children()
{
    return $this->hasMany(Category::class, 'parent_id');
}

public function parent()
{
    return $this->belongsTo(Category::class, 'parent_id');
}

But you have there just parent.

ComputerMaverick's avatar

I know that sir. However it says children property of collection instance doesn't exist despite the fact that it does exist.

MichalOravec's avatar

@computermaverick

@foreach($category->children as $subcategory)
    <p class="text-muted mb-0 pt-4">{{ $subcategory->name }}</p>
@endforeach

$category not $categories

Please or to participate in this conversation.