首页 > 解决方案 > Laravel Eloquent query/subquery with no values throws error

问题描述

All of my departments need to submit various reports each quarter: budget, HR, etc. I want to show a table that shows all of the required reports for the logged-in user's department (all departments must submit the same reports), a boolean if they have submitted it, and a boolean if that file is considered valid. I'm having problems mostly with the boolean values.

I have three tables: reports stores the id, name, and due_date; file_uploads stores the id, report_id, filename, and department_id; file_upload_errors stores id, file_upload_id, and error.

In order to build the table to display to the user, I've queried the Reports table:

$data = Reports::with([
    'file_uploads' => function ($query) {
        $query->where('department_id', '=', user()->department_id);
    },
    'file_uploads.file_upload_errors'
])->get();

Next, I need to map the data to my view model:

$vm = array();
//map the data to the view model
foreach ($data as $value) {
    $mapping = new DataRequestsViewModel();
    $mapping->ReportName = $value->name;
    $mapping->DueDate = $value->due_date;
    $mapping->IsUploaded = ($value->file_uploads->count() > 0) ? true : false;
    $mapping->IsValid = ($value->file_uploads->file_upload_errors->count() < 1) ? true : false;
    $vm[] = $mapping;
}

However, I'm getting an exception: Property [file_upload_errors] does not exist on this collection instance.

I understand this is because if the user has not yet uploaded the file, then it can't query the relationship of null to see if there are any file_upload_errors but I don't know how to handle it... Can someone show me a good approach?


I didn't actually end up using empty() when all is said and done, but it did lead me down the right path... here's what I ended up with:

foreach ($data as $value) {
            $mapping = new DataRequestsViewModel();
            $mapping->TemplateId = $value->id;
            $mapping->TemplateName = $value->name;
            $mapping->DueDate = $value->due_date;
            $mapping->IsUploaded = ($value->file_uploads->count() > 0) ? true : false;
            if ($mapping->IsUploaded == false) {
                $mapping->IsValid = false;
            } else {
                $mapping->IsValid = $value->file_uploads->first()->file_upload_errors->count() < 1 ? true : false;
            }
            $vm[] = $mapping;
        }

标签: phplaraveleloquent

解决方案


我完全在这里猜测,但我认为这是因为您正在对您的 进行自定义查询file_uploads,您实际上会丢失内置file_uploads.file_upload_errors映射。

移动查询with内部file_uploads,它将正确地将其附加到该集合中。

也许这会起作用:

$data = Reports::with([
    'file_uploads' => function ($query) {
        $query->where('department_id', '=', user()->department_id)
        ->with('file_upload_errors');
    },
])->get();

推荐阅读