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
相关产品推荐
相关产品推荐

