“with”和“each”中的 Laravel 临时属性在一起

问题描述 投票:0回答:1

我正在尝试在查询生成器中使用 Laravel each 方法,但我在 every 方法中添加的属性不会保留到集合中。当我在每个方法中

dd($task);
时,我的属性确实会显示。

$projects =
    Project::with(['tasks' => function($query) {
        $query
        ->whereBetween('start_date', ['2024-04-21', '2024-04-28'])
        ->orWhereBetween('end_date', ['2024-04-21', '2024-04-28'])
        ->each(function($task, $key) {
            //if statements here 
            $task->test = 'test';
            $task->setAttribute('date', $task->end_date);

            // dd($task); <- this returns the 'test' and 'date' attributes above
        });
    }])
    ->status(['Active', 'Scheduled'])->sortByDesc('last_status.start_date');
// dd($projects->first()->tasks->first()); <- this is missing the 'test' and 'date' attributes from above
php laravel eloquent collections laravel-query-builder
1个回答
0
投票

TL;博士

您不能在

each
中使用
with
,因为它实际上并未返回模型,它只是使用查询并稍后组合数据。

跳至下面的解决方法部分以获取潜在的解决方案。

“与”如何运作

Eloquent 使用

with
允许嵌套关系作为层次结构返回。这与
join
查询不同,其中两个模型的属性都作为包含所有属性的一个对象返回

在幕后,Eloquent 对每个

with
关系执行单独的查询,然后在返回结果之前在内存中构建对象层次结构。

在你的情况下会有一个

select *
from projects

随后

select *
from tasks
where project_id in (1,2,3 ...) -- all the project.id values
and ... -- your additional where clauses

然后使用任务对象中的外键将

projects
集合与其相关的
tasks
合并。

按照合同,

each
是一个回调,应用于查询执行后返回的所有模型。通过在 each
 内的查询上使用 
with
,它会强制 Eloquent 立即执行它并返回查询以供以后执行;但在构建对象层次结构时似乎忽略了
each

在我的本地项目上进行测试时,我看到第二个查询 -

with

 闭包内的查询 - 执行了两次,尽管只需要一次即可获取与 
tasks
 关联的所有 
project

解决方法

要向

task

 模型添加属性,您可以执行单独的查询并组合结果。

// Get all the projects $projects = Project::all(); // Get tasks for these projects $projectIds = $projects->pluck('id'); // Add attributes to the task $tasks = Task::whereIn('project_id', $projectIds)->get()->each(function ($task) { $task->test = 'test'; })->groupBy('project_id'); // Combine projects and tasks foreach ($projects as $project) { $project->tasks = $tasks[$project->id] ?? collect(); }
    
© www.soinside.com 2019 - 2024. All rights reserved.