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

Laravel 11:如何正确调用模型中的自定义方法?

问题分析与解决方案

你用with('Countries')调用失败的核心原因是:with()是Laravel Eloquent用来预加载关联关系的方法,它只识别模型中定义的Eloquent关联(如hasMany、belongsTo等),而你写的Countries()只是一个普通的模型方法,并不属于关联关系范畴。

下面分两种场景给出正确的实现方式:

场景1:仅封装查询逻辑(无需关联)

如果你的需求只是把获取国家列表的SQL逻辑封装到模型里,推荐使用本地查询作用域(Local Scope),这是Laravel官方推荐的封装查询逻辑的方式:

修改模型代码

class Terroir extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'type',
        'terroir_id',
    ];

    // 本地查询作用域,方法名以scope开头
    public function scopeCountries($query)
    {
        return $query->select(['name','id'])
            ->where('type', 1)
            ->whereNull('terroir_id')
            ->orderBy('name', 'ASC');
    }
}

调用方式

// 获取国家列表
$countries = App\Models\Terroir::countries()->get();

查询作用域支持链式调用其他查询条件,比如:

$countries = App\Models\Terroir::countries()->where('name', 'like', '%China%')->get();

场景2:定义Eloquent关联(如果需要关联关系)

如果你的Countries()是想定义Terroir模型和自身的关联(比如某个Terroir属于某个国家Terroir),那需要重新定义关联关系:

修改模型代码

class Terroir extends Model
{
    use HasFactory;

    protected $fillable = [
        'name',
        'type',
        'terroir_id',
    ];

    // 定义关联:获取所有顶级国家Terroir(type=1且无父级)
    public function countries()
    {
        // 注意:这里返回关联查询构建器,不要直接调用get()
        return $this->hasMany(self::class, 'terroir_id')
            ->where('type', 1)
            ->select(['name','id'])
            ->orderBy('name', 'ASC');
    }
}

调用方式

获取单个Terroir关联的国家:

$terroir = App\Models\Terroir::find(1);
$countries = $terroir->countries; // 直接调用关联属性,自动执行查询

预加载关联(用with()):

// 获取所有Terroir并预加载它们关联的国家
$terroirs = App\Models\Terroir::with('countries')->get();

根据你的需求描述,你只是想获取国家列表,所以场景1的查询作用域更适合你。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 18:15:06