> For the complete documentation index, see [llms.txt](https://overfinch.gitbook.io/cheatsheet/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overfinch.gitbook.io/cheatsheet/laravel/derevo-kategorii-laravel.md).

# Дерево категорий Laravel

<div><figure><img src="https://1562788351-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMyA51SCneIPcN69HMpat%2Fuploads%2FInTo0X6bCi8HwdoOwje6%2F173234076-6c76bd2b-7398-4515-9681-8967d9530fca.png?alt=media&amp;token=6ea727ac-f47f-49a4-8439-c1dba53ab668" alt=""><figcaption></figcaption></figure> <figure><img src="https://1562788351-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FMyA51SCneIPcN69HMpat%2Fuploads%2FFAEudxnIfUTBYeUmL5Cn%2F173234083-eacd715f-0c91-4b7e-89fe-2f8b2ac99efa.png?alt=media&amp;token=df6249a9-ef4c-4643-b5da-da293dd24611" alt=""><figcaption></figcaption></figure></div>

Сидинг БД таблицы категорий

<details>

<summary>Мграции и сиддинг</summary>

{% code title="create\_categories\_table" %}

```php
public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->integer('p_id');
            $table->timestamps();
        });
    }
```

{% endcode %}

<pre class="language-php" data-title="seed.php"><code class="lang-php"><strong>        Categories::factory()->create([
</strong>            'id' => 1,
            'name' => 'Главная',
            'p_id' => 0,
        ]);
        Categories::factory()->create([
                'id' => 2,
                'name' => 'Компьютеры',
                'p_id' => 1,
        ]);
        Categories::factory()->create([
                'id' => 3,
                'name' => 'Телефоны',
                'p_id' => 1,
        ]);
        Categories::factory()->create([
                'id' => 4,
                'name' => 'Планшеты',
                'p_id' => 1,
        ]);
        Categories::factory()->create([
                'id' => 5,
                'name' => 'Ноутбуки',
                'p_id' => 2,
        ]);
        Categories::factory()->create([
                'id' => 6,
                'name' => 'ПК',
                'p_id' => 2,
        ]);
        Categories::factory()->create([
                'id' => 7,
                'name' => 'Lenovo',
                'p_id' => 5,
        ]);
        Categories::factory()->create([
                'id' => 8,
                'name' => 'Apple',
                'p_id' => 5,
        ]);
        Categories::factory()->create([
                'id' => 9,
                'name' => 'Asus',
                'p_id' => 5,
        ]);
        Categories::factory()->create([
                'id' => 10,
                'name' => 'Acer',
                'p_id' => 5,
        ]);
        Categories::factory()->create([
                'id' => 11,
                'name' => 'Apple',
                'p_id' => 3,
        ]);
        Categories::factory()->create([
                'id' => 12,
                'name' => 'Samsung',
                'p_id' => 3,
        ]);
        Categories::factory()->create([
                'id' => 13,
                'name' => 'Nokia',
                'p_id' => 3,
        ]);
        Categories::factory()->create([
                'id' => 14,
                'name' => 'Huawei',
                'p_id' => 3,
        ]);
        Categories::factory()->create([
                'id' => 15,
                'name' => 'Xiaomi',
                'p_id' => 3,
        ]);
        Categories::factory()->create([
                'id' => 16,
                'name' => 'Apple',
                'p_id' => 4,
        ]);
        Categories::factory()->create([
                'id' => 17,
                'name' => 'Xiaomi',
                'p_id' => 4,
        ]);
        Categories::factory()->create([
                'id' => 18,
                'name' => 'Apple',
                'p_id' => 6,
        ]);
</code></pre>

</details>

Модель category

{% code title="Categories.php" %}

```php
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Categories extends Model
{
    use HasFactory;

    public static function getCategories(){
        // Получаем одним запросом все разделы
        $arr = self::orderBy('name')->get();
        // Запускаем рекурсивную постройку дерева и отдаем на выдачу
        return self::buildTree($arr, 0);
    }

    public static function buildTree($arr, $pid = 0) {
        // Находим всех детей раздела
        $found = $arr->filter(function($item) use ($pid){return $item->p_id == $pid; });

        // Каждому детю запускаем поиск его детей и записываем в свойство sub
        foreach ($found as $key => $cat) {
            $sub = self::buildTree($arr, $cat->id);
            // То что ниже можно заменить на - $cat->sub = $sub;
            $found[$key]->sub = $sub;
        }

        return $found;
    }

    // Альтернативный вариант

    public static function getCategories2(){ // получаем корневые категории (у которых нету родителей) с жадной загрузкой отношения categories()
        return self::where('p_id','=',0)->with('categories')->get();
    }

    public function categories(){ // отношение категории к дочерним категориям, отдаётся сразу с жадной загрузкой
        return $this->hasMany(self::class,'p_id','id')->with('categories');
    }
}
```

{% endcode %}

Контроллер&#x20;

{% code title="TreeController.php" %}

```php
namespace App\Http\Controllers;

use App\Models\Categories;
use Illuminate\Http\Request;

class TreeController extends Controller
{
    public function index(){
        $categories = Categories::getCategories();
        return view('tree')->with(['categories' => $categories]);
    }

    public function index2(){
        $categories = Categories::getCategories2();
        return view('tree2')->with(['categories' => $categories]);
    }
}
```

{% endcode %}

Первый вариант

{% code title="tree.blade.php" %}

```php
<ul>
    @foreach($categories as $category)
        <li>
            {{$category->name}}
            @if($category->sub->count())
                @include('tree', ['categories' => $category->sub])
            @endif
        </li>
    @endforeach
</ul>
```

{% endcode %}

Второй вариант (предпочтительный) через жадную загрузку отношений самих на себя

{% code title="tree2.blade.php" %}

```php
<ul>
    @foreach($categories as $category)
        <li>
            {{$category->name}}
            @if($category->categories->isNotEmpty())
                @include('tree2',['categories' => $category->categories])
            @endif
        </li>
    @endforeach
</ul>
```

{% endcode %}
