获取每个产品的第一张图片

Get first image for each product

我尝试获取最新的 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

它在 productimage

之间有一个 morph 关系

产品型号

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

图片模型

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

当使用 with 作为键值数组时,闭包的 $el 参数将是一个尚未执行的查询构建器。

限制结果查询生成器的方法是使用take()。因此你的代码应该是这样的。

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

编辑 要使此解决方案有效,您需要额外的 package. Using the following trait should make it work and using limit instead. See the following .

use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;

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

或者Laravel解决方案是使用像属性这样的转换,您可以在其中创建自己的自定义属性,在以get开头并以attribute结尾的函数命名中。

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

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

现在,如果您使用标准 Laravel 序列化,所有产品都会有一个 first_image 字段,您可以在您的代码中像这样访问它。

$product->first_image;

为避免性能下降,请使用 with('images').

添加图像

以上解决方案都很好。我个人更喜欢我认为会很理想的不同解决方案。

我要为产品定义不同的关系:

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.

中从 Jonathan Reinink 那里学到了这个和其他有用的数据库技巧
public function images()
{
    return $this->hasMany(Image::class);
}

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

只需创建一个函数来定义产品与其图像之间的关系。 然后创建一个获取第一张图片的函数