简体   繁体   中英

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;
        }

You don't handle it :) If there is no error then there is no need to count them. I'd use this instead:

$mapping->IsValid = empty($value->file_uploads->file_upload_errors) ? true : false;

I'm totally guessing here, but I think it's because you're doing a custom query on your file_uploads , that you actually lose the built-in file_uploads.file_upload_errors mapping.

Moving the with inside the file_uploads query, it will append it to that collection properly.

Perhaps this will work:

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

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