简体   繁体   中英

Create a tree structure from two tables

So, my problem is that I need to build a tree with data from two tables.

I have the following tables:

Category:

| id | parent_id | name           |
|----|-----------|----------------|
| 1  | null      | Category 1     |
| 2  | 1         | Category 1.1   |
| 3  | 2         | Category 1.1.1 |
| 4  | null      | Category 2     |
| 5  | 4         | Category 2.1   |
| 6  | null      | Category 3     |


Layer:

| id | category_id | name    |
|----|-------------|---------|
| 1  | 2           | Layer 1 |
| 2  | 2           | Layer 2 |
| 3  | 3           | Layer 3 |
| 4  | 4           | Layer 4 |
| 5  | 4           | Layer 5 |
| 6  | 5           | Layer 6 |

My Category model:

class Category extends Model
{
    public function parent()
    {
        return $this->belongsTo('App\Category', 'parent_id');
    }

    public function childrens()
    {
        return $this->hasMany('App\Category', 'parent_id', 'id');
    }

    public function layers()
    {
        return $this->hasMany('App\Layer', 'category_id', 'id');
    }
}

Layer model:

class Layer extends Model
{
    public function category()
    {
        return $this->belongsTo('App\Category', 'category_id');
    }
}

I'm using the following function to build the category tree:

public function index()
{
    $categories = Category::all();
    $layers = Layer::all();

    return $this->buildTree($categories->toArray(), null);
}


function buildTree($categories, $parent_id)
{
    $categoriesTree = [];
    foreach ($categories as $category) {
        $category['folder'] = true;

         if ($category['parent_id'] == $parent_id) {
            $childrens = $this->buildTree($categories, $category['id']);
            if ($childrens) {
                $category['childrens'] = $childrens;
            }

            $categoriesTree[] = $category;
        }
    }

    return $categoriesTree;
}

The above function works well for categories and the response is:

  • Category 1
    • Category 1.1
      • Category 1.1.1
  • Category 2
    • Category 2.1
  • Category 3

But I want to add layers as child of respective category, like the following:

  • Category 1
    • Category 1.1
      • Category 1.1.1
        • Layer 3
      • Layer 1
      • Layer 2
  • Category 2
    • Category 2.1
      • Layer 6
    • Layer 4
    • Layer 5
  • Category 3

What is the best way to do this?

I suggest using arelationship in your Category model with the Layer model and eager load it. This way you achieve the same result but with less overhead on your buildTree function because Laravel is doing most of the work:

Category.php model

class Category extends Model
{
    // ...

    public function layers()
    {
        return $this->hasMany(Layer::class);
    }

    // ...
}

In your controller:

public function index()
{
    $categories = Category::with('layers')->get();

    // ...
}

This results in an array like this:

每个类别的急切加载层

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM