Преобразование в Laravel Collection / Метод карты. Непоследовательное поведение - PullRequest
1 голос
/ 30 мая 2019

В моем 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
            ];
        })]);

Я на самом деле просто фильтрую записи, созданные определенными идентификаторами пользователей (вызов whereIn() в строке 4. Однако ответ, отправленный обратно клиенту, выглядит по-разному для разных пользователей, отфильтрованных, что приводит к тому, что таблица jQuery показывает «нет записей» доступный », поскольку он получил неверно сформированный ответ от сервера. Для одного пользователя ответ выглядит следующим образом:

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

Это правильно сформированный ответ сервера, который будет регулярно отображаться в таблице. Большой! Теперь то, что сводит меня с ума - тот же код для другого пользователя (идентификатор 1, в то время как первый запрос был для идентификатора пользователя 2) возвращает это:

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

, который, очевидно, искажен и неправильно анализируется данными. Хорошо, теперь объединение их двумя фильтрами и фильтрацией для идентификаторов пользователя 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>"
      ]
   ]
}

Я попробовал несколько вещей, ни одна из которых не сработала, так как я просто догадывался, почему он может работать с одним пользователем, а не с другим. (Такие вещи, как изменение порядка идентификаторов для фильтрации и т. Д., Но я обнаружил, что фильтрация не является проблемой. Это ДОЛЖНО быть преобразование, которое ведет себя противоречиво.)

Любые идеи о том, почему это происходит и как с этим бороться? Я имею в виду, это не единственный способ добиться того, чего я добиваюсь, я использовал ->each() и array_push для всех раньше, но хотел избавиться от него ради использования помощников (или возможностей) Laravel - ручной итерации и процесс переброса массива раньше без проблем работали, и даже другие части приложения хорошо работают с преобразованием Collection через массив итерация и нажатие. Почему здесь нет?

Обновление: метод сбора ->map() ведет себя точно так же. Map, в отличие от transform, не изменяет саму коллекцию. Тем не менее, это не должно быть соответствующей частью в этом приложении в любом случае. Я действительно не могу понять, что происходит не так. Возможно, это вина Ларавела?

Ответы [ 2 ]

0 голосов
/ 30 мая 2019

@ Ответ Цветана Михайлова заставил меня взглянуть на все доступные методы сбора (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()]);
0 голосов
/ 30 мая 2019

Обратите внимание, что метод 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()]);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...