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

时间:2020-01-08 21:16:44

标签: php laravel eloquent eloquent-relationship

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

它在morphproduct之间具有image关系

产品型号

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

图像模型

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

3 个答案:

答案 0 :(得分:2)

使用with作为键值数组时,闭包的$el参数将是尚未执行的查询生成器。

限制结果的查询构建器的方法是使用take()。因此,您的代码应如下所示。

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

编辑,要使该解决方案有效,您将需要额外的package。使用以下特征应使其起作用,而应使用限制。请参阅以下post

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')添加图像。

答案 1 :(得分:2)

以上解决方案都很好。我个人更喜欢另一种我认为将是理想的解决方案。

我要为产品定义其他关系:

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那里了解了这个以及其他有用的数据库技巧。

答案 2 :(得分:0)

public function images()
{
    return $this->hasMany(Image::class);
}

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

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