如何使用<select>标记中的嵌套项列表减少数据库查询量?

时间:2019-06-11 12:44:07

标签: php laravel laravel-5

Laravel 5.8: 使用嵌套的项目列表时,查询太多。

这是“视图”中的菜单。我已经完成了项目的嵌套菜单,但是在我看来,这需要太多的查询(我的30个项目的列表中有10个额外的查询),尽管我使用了“急切的加载”。

在模型中:

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

它的存储库:(用于急切加载[with])

public function getListOfItemTitles()
{
    $columns = ['id', 'parent_id', 'title'];

    $result = $this->startConditions()
        ->select($columns)
        ->with(['children:id,title,parent_id'])
        ->get();
    return $result;
}

视图:

<select name="item_id" id="item_id" class="form-control" required>
    @foreach($itemList as $itemOption)
        @if($itemOption->parent_id == 1)
            <optgroup label="{{ $itemOption->title }}">
                @foreach($itemOption->children as $children)
                    <option value="{{ $children->id }}">
                        {{ $children->title }}
                    </option>
                    @foreach($children->children as $subchildren)
                        <option value="{{ $subchildren->id }}">
                            —{{ $subchildren->title }}
                        </option>
                    @endforeach
                @endforeach
            </optgroup>
        @endif
    @endforeach
</select>

这是我的疑问:

select `id`, `parent_id`, `title` from `items` where `items`.`deleted_at` is null
select `id`, `title`, `parent_id` from `items` where `items`.`parent_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30) and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 4 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 8 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 12 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 16 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 20 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 26 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 27 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 28 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 29 and `items`.`parent_id` is not null and `items`.`deleted_at` is null
select * from `items` where `items`.`parent_id` = 30 and `items`.`parent_id` is not null and `items`.`deleted_at` is null

如果您能帮助我减少查询量,我会很高兴。 由于我是PhP&Laravel的新手,因此在这种情况下,任何其他建议都会非常有用。

1 个答案:

答案 0 :(得分:1)

您还必须渴望加载子子级:

$columns = ['id', 'parent_id', 'title'];

$result = $this->startConditions()
    ->select($columns)
    ->with(['children:id,title,parent_id', 'children.children:id,title'])
    ->get();
return $result;

请考虑本文中的以下示例:https://laravel-news.com/eloquent-eager-loading

$posts = App\Post::with('author.profile')->get();
$posts->map(function ($post) {
    return $post->author->profile;
});

在这里您可以看到他们使用点符号来使用with()

获取深层关系