Получить первое изображение для каждого продукта - PullRequest
1 голос
/ 09 января 2020

Я пытаюсь получить последние 10 продукты с его изображениями, но только первое изображение, вот что я пытаюсь

$newProducts = \App\Product::latest()->with(['images', function($el){

   $el->first();

}])->with('category')->take(10)->get();

, но это дает мне эту ошибку

mb_strpos() expects parameter 1 to be string, object given

имеет отношение morph между product и image

Модель продукта

class Product extends Model {
    public function images()
    {
        return $this->morphMany(Image::class, 'imageable');
    }
}

Изображение Модель

class Image extends Model {
    public function imageable()
    {
        return $this->morphTo();
    }
}

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Все вышеперечисленные решения хороши. Я лично предпочитаю другое решение, которое, я думаю, будет идеальным.

Я определю другое отношение для продукта:

class Product extends Model {
    public function images()
    {
        return $this->morphMany(Image::class, 'imageable');
    }

    public function firstImage()
    {
        return $this->morphOne(Image::class, 'imageable');
    }
}

Так что вы можете получить доступ к первому изображению напрямую или с нетерпением загрузить отношения:

$product->firstImage;

$product->load('firstImage');

Product::with('firstImage');

Просто к вашему сведению, я узнал об этом и других полезных трюках с базой данных от Джонатана Рейнинка в Laracon Online 2018 .

2 голосов
/ 09 января 2020

При использовании с в качестве массива значений ключей параметром $el для замыкания будет построитель запросов, который еще не выполнен.

Способ ограничения создателей запросов результатов заключается в использовании take(). Поэтому ваш код должен выглядеть следующим образом.

->with(['images', function($el) {
    $el->take(1);
}])

Редактировать Чтобы это решение работало, вам понадобится дополнительный пакет . Использование следующей черты должно заставить его работать и вместо этого использовать лимит. См. Следующий post .

use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;

->with(['images', function($el) {
    $el->limit(1);
}])

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

class Product {
    protected $appends = ['first_image'];

    public function getFirstImageAttribute() {
        return $this->images->first();
    }
}

Теперь, если вы используете стандартную сериализацию Laravel, все продукты будут иметь поле first_image, и в вашем коде вы сможете получить к нему доступ таким образом.

$product->first_image;

Чтобы избежать снижения производительности, добавьте изображения, используя with('images').

...