laravel pluck 5.2 не работает как в 5.1

Код ниже работал в версии 5.1, и логотипы загружались лениво. Но теперь он пытается вызвать метод загрузки для коллекции.

$campaigns = Campaign::all();
$campaigns->pluck('brand')->load('logo');

Ошибка

in Macroable.php line 81
at Collection->__call('load', array('logo')) in HomeController.php line 84
at Collection->load('logo') in HomeController.php line 84
at HomeController->index(object(Request))

5.1 с ошибкой неправильного отношения

in Builder.php line 2071
at Builder->__call('logo1', array())
at Builder->logo1()
at call_user_func_array(array(object(Builder), 'logo1'), array()) in Builder.php line 943
at Builder->__call('logo1', array())
at Builder->logo1()
at call_user_func_array(array(object(Builder), 'logo1'), array()) in Model.php line 3483
at Model->__call('logo1', array()) in Builder.php line 477
at Brand->logo1() in Builder.php line 477
at Builder->Illuminate\Database\Eloquent\{closure}()
at call_user_func(object(Closure)) in Relation.php line 171
at Relation::noConstraints(object(Closure)) in Builder.php line 478
at Builder->getRelation('logo1') in Builder.php line 449
at Builder->loadRelation(array(object(Brand), object(Brand), object(Brand), object(Brand), object(Brand), object(Brand), object(Brand)), 'logo1', object(Closure)) in Builder.php line 429
at Builder->eagerLoadRelations(array(object(Brand), object(Brand), object(Brand), object(Brand), object(Brand), object(Brand), object(Brand))) in Collection.php line 44
at Collection->load('logo1') in HomeController.php line 82

Выясните, что это было Illuminate\Database\Eloquent\Collection, а теперь Illuminate\Support\Collection.

Как я могу преобразовать его в Eloquent?


person ymutlu    schedule 10.03.2016    source источник


Ответы (2)


Инициируйте новую коллекцию Eloquent с результатом pluck, и она снова заработала. Я надеюсь, что есть лучшее решение.

    $b = new \Illuminate\Database\Eloquent\Collection($campaigns->pluck('brand'));
    $b->load('logo');
person ymutlu    schedule 10.03.2016

Вы должны проверить документы Laravel здесь: как указано во вводной заметке

Примечание. В то время как большинство методов коллекции Eloquent возвращают новый экземпляр коллекции Eloquent, методы pluck, keys, zip, свернуть, сгладить и перевернуть возвращают экземпляр базовой коллекции.

Коллекция Eloquent — это просто расширение коллекции Illuminate\Support\Collection. В Eloquent Collection конструктор не переопределяется, поэтому, проверяя конструктор Base Controller, мы можем предположить, что вы можете создать Eloquent Collection (или новую Base Collection) с таким типом/экземплярами:

  • Множество
  • Коллекция (экземпляр self)
  • Массив (экземпляр)
  • Jsonable (экземпляр)
  • JsonSerializable (экземпляр)

Вы можете проверить метод __construct класса Collection в папке вашего поставщика, в laravel\framework\Illuminate\Support\Collection.php, а затем найти метод getArrayableItems, который вызывается в конструкторе.

По моему скромному мнению, создание коллекции Eloquent из «базовой» коллекции совершенно бесполезно, так как вы потеряете ссылки на базу данных и больше не сможете напрямую работать с этим набором результатов. На самом деле у вас не будет идентификатора или какого-либо первичного ключа, который позволит вам идентифицировать точную строку в вашей базе данных (если ваши извлеченные данные не являются первичным ключом). В любом случае, вы можете создать экземпляр новой коллекции Eloquent, передав «базовую» коллекцию в конструкторе:

$baseCollection = new \Illuminate\Support\Collection();
$eloquentCollection = new \Illuminate\Database\Eloquent\Collection($baseCollection);

Кроме того, с помощью Campaign::all() вы извлекаете все столбцы из таблицы. Почему бы тебе просто не

Campaign::with('logo')->get(['id', 'brand']);

Ленивая загрузка сделает запрос для каждого элемента в вашей коллекции. Вместо этого активная загрузка выполнит ее гораздо быстрее, предоставив все необходимые данные за небольшое количество запросов.

person Andrew Alhena    schedule 10.03.2016
comment
Спасибо за подробное объяснение. Campaign::all() предназначен только для демонстрации. И логотип не является отсылкой к кампании, он принадлежит бренду. Кажется, что инициировать новую коллекцию элогентов — лучший выбор. - person ymutlu; 11.03.2016