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

bbenToker's avatar

Creating a categories tree

I am trying to create a visual category tree in a dynamic structure.Because of my system allows admin users to add as much as categories as they want and have the relationship between them as they want,ı must create my tree dynamically.

public function sort($x=NULL)
   {
       $Categories = Category::where('parent',$x)->get();
       static $data = array();
       foreach($Categories as $category)
       {
           array_push($data,$category);
           
           if(isset($category->child))
           {
               self::sort($category->id);
           }
       }
       return $data;
   }

With this code block I can acces my categories in the order I want but the thing is I couldn't figure out how to add spaceses before every child category.Since ı can't use recursice functions in the blade files I am strugging. Think of my category as data trees but sideways and every step into the child category means an extra space so that visually they can be seen inside of thier parent category.

0 likes
2 replies
tykus's avatar
tykus
Best Answer
Level 104

You can create a relationship which fetches all children recursively:

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

Now, whenever you fetch a Category; eager-load the children:

$categories = Category::where('parent',$x)->with('children')->get();

Finally, using a Blade component, you can render the tree:

@foreach($categories as $category)
    <x-category :category="$category" />
@endforeach

The component will render the Category properties and recursively render the children. I am using padding-left to indent, but you can change as appropriate:

<div>
	{{ $category->name }}
	<div style="padding-left: 1rem">
        @foreach($category->children as $category)
            <x-category :category="$category" />
        @endforeach
    </div>
</div>
1 like
bbenToker's avatar

@tykus I managed to solve the problem in a more troublesome way

public function sort($x=NULL,$m=0)
   {
       $Categories = Category::where('parent',$x)->get();
       static $data = array();
       static $metadata = array();
       foreach($Categories as $category)
       {   
           array_push($metadata,$m);
           array_push($data,$category);
           
           if(isset($category->child))
           {   
               self::sort($category->id,++$m);
           }
           $m--;
       }
       return [$data,$metadata];
   }
 public function index()
   {   
       [$Categories,$Spaces] = self::sort();
       return view('playground',compact('Categories','Spaces'));
   }
@extends('voyager::master')

@section('content')
<select name="parent" id="parent">
   @for($n=0,$i = count($Categories);$n<$i;$n++)
       @for($a=0,$b=$Spaces[$n];$a<$b;$a++)
           <!--printf(" ");-->HTML version
       @endfor
       <!--print_r($Categories[$n]->name);
       printf("\n");-->HTML version
   @endfor
</select>
@endsection

Seeing the way you solved the problem made so much sense,so thanks for that I'll adjust my code according to that.And please don't mind that I don't know much about HTML and CSS

Please or to participate in this conversation.