AD Henrique
AD Henrique

Reputation: 195

How to make a hierarchical table with laravel?

I'm developing a simple plataform of schoolwork. The plataform have two tables: themes - where the themes of each job will be saved

id
parent_id
name

works - here will be the works of each student

id
theme_id
description

Well, I'm trying to make a hierarchical table. Where each row would have the theme and when you open the row, it would show the works of the theme and if there is a child-theme, it would show the link to this ... and so on!

Something like this: hierarchical table

In model, i have:

public function childs() {
    return $this->hasMany(self::class,'parent_id','id') ;
}

In my controller (i need to improve this):

public function index(){
    $themes = DB::table('themes', DB::raw('SELECT * WHERE lft IS BETWEEN parent.lft AND parent.rgt'))->get();
    $works = Work::all();

    $themes = array_map(function($theme){
        $theme->works = [];
        return $theme;
    }, $themes->toArray());

    foreach($themes as $theme){
        foreach($works as $work){
            if($theme->id === $work->theme_id){
                $theme->works[] = $work;
            }
        }
    }
    return view('dashboard.trabalhos.index', ['themes' => $themes]);
}

The return of the controller function is:

array:3 [▼
  0 => {#275 ▼
    +"id": 1
    +"parent_id": null
    +"name": "Tema1"
    +"description": "asdasdasd"
    +"lft": 1
    +"rgt": 6
    +"depth": 0
    +"created_at": null
    +"updated_at": null
    +"works": array:1 [▼
      0 => Work {#287 ▶}
    ]
  }
  1 => {#278 ▶}
  2 => {#279 ▶}
]

And in the view, my last test was something like this:

<table id="asd" class="highlight">
    <thead>
    <tr>
        <th>Tema</th>
    </tr>
    </thead>
    <tbody>
    @forelse($themes as $theme)
        @php($asd = $theme->depth)
        @if($theme->depth === 0)
            <tr data-tt-id="{{$theme->id}}" class="branch collapsed">
                <td>

                    @if(count($theme->works) > 0)
                        <?php
                        foreach($theme->works as $work){
                            echo "nome: " . $work->title;
                        }
                        ?>
                    @endif
                    {{$theme->name}}
                </td>
            </tr>
        @elseif($theme->depth > 0)
            <tr data-tt-id="{{$theme->id}}" data-tt-parent-id="{{$theme->parent_id}}"  class="branch collapsed" style="display: none;">

                <td>
                    {{$theme->name}}
                </td>
            </tr>
        @endif
    @empty

    @endforelse
    <tr></tr>
    </tbody>
</table>

I've tried using bootstrap-treeview and treetable but maybe my problem is logic in frontend. Could someone help me and give me a light?

Upvotes: 2

Views: 1142

Answers (1)

omadonex
omadonex

Reputation: 541

You can look at component "kalnoy/nestedset" It's a component for building tree structures and it contains all neccessary methods for it. If you will using it, you need to add specified columns to a table like this

Schema::create('items', function (Blueprint $table) {
    $table->increments('id');
    ...
    NestedSet::columns($table);
    ...
});

And the you can use all of methods of this component to generate tree structures like this:

$root = Item::findOrFail($rootId);
$nodes = $root->descendants->toTree($root);

$traverse = function ($items, $prefix = '-') use (&$traverse) {
    $html = '';
    foreach ($items as $item) {
        $html .= ... (html structure)
        $html .= $traverse($item->children, $prefix . '-');
    }
    return $html;
};

$html .= $traverse($nodes);

Upvotes: 1

Related Questions