【问题标题】:Laravel Collection Transform/Map Method Inconsistent BehaviourLaravel 集合变换/映射方法不一致的行为
【发布时间】:2019-10-15 21:15:13
【问题描述】:

在我的 HTML 前端,我有一个 jQuery DataTable 显示通过 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顺序等等,但我发现过滤不是问题。它必须是转换,它的行为不一致。)

关于为什么会发生这种情况的任何想法以及如何解决它?我的意思是,这不是实现我所追求的唯一方法,我使用-&gt;each()array_push 为所有人之前的时间,但为了利用 Laravel 的助手(或可能性)而想摆脱它 - 手动迭代和数组推送过程之前无缝地工作,甚至应用程序的其他部分也可以很好地与 Collection 转换数组迭代和推送。为什么不在这里?

更新:-&gt;map() 收集方法的行为完全相同。 Maptransform 相反,不会改变集合本身。但是,这不应该是本应用程序中的相关部分。我真的不明白出了什么问题。这可能是 Laravel 的错吗?

【问题讨论】:

    标签: php laravel


    【解决方案1】:

    @Cvetan Mihaylov 的回答让我查看了所有可用的收集方法 (https://laravel.com/docs/5.8/collections#available-methods),我发现 -&gt;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()]);
    

    【讨论】:

    • 嗯,使用-&gt;values()-&gt;all() 更好,这有点奇怪,因为values() 仍然返回一个集合,然后当它在response()-&gt;json() 打电话。而 -&gt;all() 返回一个数组,并且很清楚您之后要序列化的内容。无论如何,很高兴您找到了解决方案。如果你觉得这个答案有用,你可以投赞成票。
    • 嗯,神奇的是/是 Laravel 集合产生的 Arrayable 和 Jsonable 特征。同样,您可以通过 $collection['key'] 访问集合值。
    【解决方案2】:

    请注意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()]);
    
    

    【讨论】:

    • 感谢您的建议。这个在阅读时已经给了我希望,但被证明是错误的,因为它返回完全相同的东西(这对我来说没有意义)。
    猜你喜欢
    • 1970-01-01
    • 2018-08-24
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多