You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel本地作用域问题:如何获取商品的首个有效优惠券?

Laravel模型本地作用域:获取商品首个有效优惠券的正确实现

问题场景

现有Laravel的Product和Voucher模型,关联关系如下:

Product模型:

class Product extends Model {
    public function vouchers(): HasMany {
          return $this->hasMany(Voucher::class);
    }
}

Voucher模型:

class Voucher extends Model {
    public function product(): BelongsTo {
        return $this->belongsTo(Product::class);
    }
}

voucher表包含status字段,取值为active或inactive。需要实现获取某一商品的首个有效优惠券,但原本地作用域写法报错:

Property [vouchers] does not exist on the Eloquent builder instance.

原错误代码:

public function scopeActiveVouchers($query)
{
    return $query->vouchers->first()->where('status', 'active');
}

错误原因

本地作用域的参数$query是Eloquent Builder实例,而vouchers是定义在Product模型上的关联方法,Builder对象无法直接访问该属性,必须通过调用关联方法(vouchers())来获取关联查询的Builder实例,再添加条件。

正确实现方案

方案1:为Product实例添加方法获取首个有效优惠券

如果需求是针对单个Product实例获取其首个有效优惠券,更适合定义模型方法而非本地作用域:

class Product extends Model {
    public function vouchers(): HasMany {
          return $this->hasMany(Voucher::class);
    }

    // 获取当前商品的首个有效优惠券
    public function firstActiveVoucher()
    {
        return $this->vouchers()->where('status', 'active')->first();
    }
}

调用方式:

$product = Product::find($productId);
$activeVoucher = $product->firstActiveVoucher();

方案2:使用本地作用域预加载首个有效优惠券

如果需要在查询Product时批量预加载每个商品的首个有效优惠券,可以定义如下本地作用域:

class Product extends Model {
    public function vouchers(): HasMany {
          return $this->hasMany(Voucher::class);
    }

    public function scopeWithFirstActiveVoucher($query)
    {
        return $query->with(['vouchers' => function ($q) {
            $q->where('status', 'active')->take(1);
        }]);
    }
}

调用方式:

// 查询商品并预加载首个有效优惠券
$product = Product::withFirstActiveVoucher()->find($productId);
// 获取首个有效优惠券
$activeVoucher = $product->vouchers->first();

补充说明

本地作用域的核心用途是约束Product模型的查询条件,比如筛选出存在有效优惠券的商品;而如果是获取单个商品的关联数据,直接定义模型方法会更直观。

内容的提问来源于stack exchange,提问作者wiwa1978

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 22:57:24