Laravel filtered collection 经过json 编码后不再过滤

Laravel filtered collection is no longer filtered after json encoding

我有一个 Eloquent collection 有一个急切的加载关系。当我过滤这个急切加载的关系时,它工作正常,但如果我将它编码为 JSON(将它传递给我的前端 Javascript 框架),则 collection 不再被过滤。

简化示例:

$questions = Question::with('variables')->get();

foreach($questions as $key => $q) {
  $questions[$key]->variables = $q->variables->reject(function($v) {
    return $v->type == 3;
  });
}

dd($questions);

如果我此时查看 $questions 变量,我的 collection 已被正确过滤。但是,如果我在转储之前添加 json_decode(json_encode($questions)) 下一行,则 collection 不再被过滤。

请注意,在我的实际应用程序中,我必须在将被拒绝的变量从 collection 中删除之前对它们做一些处理,因此我不能简单地在查询过程中将它们过滤掉。

我现在的解决方法是 json 对 collection 进行编码和解码,然后进行数组过滤以去除我不想传递给前端的变量。这可行,但似乎是一个非常不优雅且不必要的解决方案。我是做错了什么还是这是预期的行为?

我仍然 运行 Laravel 5.8 使用此应用程序,以防此行为在较新版本上发生变化。

为什么不加载变量两次呢?

$questions = Question::with(['variables' => fn($v) => $v->where('type', '!=', 3)])->get();
// do whatever you need to do with the filtered collection

// reload variables relationship
$questions->load('variables');
// do whatever you need to do with the question and all its variables.

你可以试试

$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)
);