Laravel集合转换/映射方法行为不一致

时间:2019-05-30 08:27:42

标签: php laravel

在我的HTML前端中,我有一个jQuery数据表,显示通过AJAX从数据库中获取的所有记录-这是相当简单的事情。我使用Laravel集合的->transform(function($o){ . . . })来遍历集合,并以类似数组的方式返回它。只需考虑一下控制器中的以下代码:

        $cAllRecords = DatabaseRecord::all();
        if(!empty($aData['sFilterIds']))
        {
            $cAllRecords = $cAllRecords->whereIn('creator', explode(',', $aData['sFilterIds']));
        }
        return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
            /** @var $oDatabaseRecord DatabaseRecord */
            $sActionsHtml = '<a href="#">edit</a>';
            $sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
            return [
                $oDatabaseRecord->getAttribute('id'),
                $oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
                $oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
                $sActionsHtml
            ];
        })]);

我实际上只是过滤某些用户ID(第4行中的whereIn()调用)创建的记录。但是,对于过滤后的不同用户,发回客户端的响应看起来有所不同,导致jQuery表显示“没有可用的记录”,因为它收到了来自服务器的格式错误的答案。对于一个用户,响应如下所示:

{
   "data":[
      [
         1,
         "2019-05-29 16:44:53",
         "2019-05-29 16:44:53",
         "<a href=\"#\">edit<\/a>"
      ]
   ]
}

这是格式正确的服务器响应,将定期显示在表格中。大!现在,让我发疯的是-另一个用户的相同代码(ID 1,而第一个请求是用户ID 2)返回以下代码:

{
   "data":{
      "1":[
         3,
         "2019-05-29 17:08:49",
         "2019-05-29 17:08:49",
         "<a href=\"#\">edit<\/a>"
      ]
   }
}

,很显然,它格式错误,并且不能被数据表正确解析。好的,现在将它们组合为两个过滤器并过滤用户ID 1和2将再次返回正确格式的响应:

{
   "data":[
      [
         1,
         "2019-05-29 16:44:53",
         "2019-05-29 16:44:53",
         "<a href=\"#\">edit<\/a>"
      ],
      [
         3,
         "2019-05-29 17:08:49",
         "2019-05-29 17:08:49",
         "<a href=\"#\">edit<\/a>"
      ]
   ]
}

我尝试了许多方法,但都没有成功,因为它只是猜测为什么它可以与一个用户一起使用而不与另一个用户一起使用。 (诸如反转要过滤的ID的顺序之类的事情,等等,但是我发现过滤不是问题。必须是转换,其行为不一致。)

关于为什么会发生这种情况以及如何解决它的任何想法?我的意思是,这不是实现我所追求的唯一方法,我正在使用->each()和{{1 }}一直以来都是如此,但为了使用Laravel的助手(或可能性)而想摆脱它-手动迭代和数组推入过程之前已经无缝完成,甚至应用程序的其他部分也能很好地与Collection通过数组迭代和推送进行转换。为什么不在这里?

更新:array_push收集方法的行为完全相同。 ->map()Map相反,它不会更改集合本身。但是,无论如何,这都不应该是此应用程序中的相关部分。我真的不明白怎么了。这可能是Laravel的错吗?

2 个答案:

答案 0 :(得分:0)

请注意,transform方法返回一个Illuminate\Support\Collection

最好在转换后调用all()以获取数组结果。

赞:

...
return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
            /** @var $oDatabaseRecord DatabaseRecord */
            $sActionsHtml = '<a href="#">edit</a>';
            $sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
            return [
                $oDatabaseRecord->getAttribute('id'),
                $oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
                $oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
                $sActionsHtml
            ];
        })->all()]);

答案 1 :(得分:0)

@Cvetan Mihaylov的回答使我研究了所有可用的收集方法(https://laravel.com/docs/5.8/collections#available-methods),发现->values()返回了重新索引的值。而且-做到了! :-)

return response()->json(['data' => $cAllRecords->transform(function ($oDatabaseRecord) {
        /** @var $oDatabaseRecord DatabaseRecord */
        $sActionsHtml = '<a href="#">edit</a>';
        $sUrl = route('some.route', ['iDatabaseRecordId' => $oDatabaseRecord->getAttribute('od')]);
        return [
            $oDatabaseRecord->getAttribute('id'),
            $oDatabaseRecord->getAttribute('updated_at')->toDateTimeString(),
            $oDatabaseRecord->getAttribute('created_at')->toDateTimeString(),
            $sActionsHtml
        ];
    })->values()]);
相关问题