I have an Eloquent collection with an eager loaded relationship. When I filter this eager loaded relationship, it works fine, but if I encode it as JSON (to pass it to my front end Javascript framework), the collection is no longer filtered.
Simplified example:
$questions = Question::with('variables')->get();
foreach($questions as $key => $q) {
$questions[$key]->variables = $q->variables->reject(function($v) {
return $v->type == 3;
});
}
dd($questions);
If I look at the $questions variable at this point, my collection is correctly filtered. If, however, I add json_decode(json_encode($questions))
following line before dumping, the collection is no longer filtered.
Note that in my real application, I have to do some things with the rejected variables before throwing them out of the collection, so I cannot simply filter them out during the query.
My workaround right now is to json encode and decode the collection, then do an array filter to get rid of the variables I do not want to pass to the front end. This works, but seems like a terribly inelegant and unnecessary solution. Am I doing something wrong or is this the expected behavior?
I'm still running Laravel 5.8 on this application in the event that this behavior has changed on newer versions.
You can try
$questionsWithFilteredVariables = $questions->map(function($question) {
$variables = $question->variables->reject(fn($var) => $var->type === 3);
unset($question->variables);
$question->variables = $variables;
return $question;
});
//Now do json_decode(json_encode(...)), it will still contain filtered variables
$questionsWithFilteredVariables = json_decode(
json_encode($questionsWithFilteredVariables)
);