我有一个Eloquent模型,它有一个相关的模型:
public function option() {
return $this->hasOne('RepairOption', 'repair_item_id');
}
public function setOptionArrayAttribute($values)
{
$this->option->update($values);
}
当我创建模型时,它不一定有相关的模型 . 当我更新它时,我可能会添加一个选项 .
所以我需要检查相关模型是否存在,分别更新或创建它:
$model = RepairItem::find($id);
if (Input::has('option')) {
if (<related_model_exists>) {
$option = new RepairOption(Input::get('option'));
$option->repairItem()->associate($model);
$option->save();
$model->fill(Input::except('option');
} else {
$model->update(Input::all());
}
};
<related_model_exists>
是我要找的代码 .
8 回答
在 php 7.2+ 中,您不能在关系对象上使用
count
,因此对于所有关系都没有一个通用的方法 . 使用查询方法改为@tremby,如下所示:处理所有关系类型的通用解决方案( pre php 7.2 ):
这将适用于每个关系,因为动态属性返回
Model
或Collection
. 两者都实现ArrayAccess
.所以它是这样的:
single relations:
hasOne
/belongsTo
/morphTo
/morphOne
to-many relations:
hasMany
/belongsToMany
/morphMany
/morphToMany
/morphedByMany
Relation object将未知方法调用传递给Eloquent query Builder,设置为仅选择相关对象 . 那个Builder又将未知的方法调用传递给它的底层query Builder .
这意味着您可以直接从关系对象使用exists()或count()方法:
注意
relation
之后的括号:->relation()
是一个函数调用(获取关系对象),而不是->relation
,这是一个由Laravel为你设置的魔法属性获取器(获取相关的对象/对象) .在关系对象上使用
count
方法(即使用括号)将比执行$model->relation->count()
或count($model->relation)
快得多(除非关系已被急切加载),因为它运行计数查询而不是拉出所有数据来自数据库的任何相关对象,只是为了计算它们 . 同样,使用exists
也不需要拉模型数据 .exists()
和count()
都适用于我尝试的所有关系类型,因此至少belongsTo
,hasOne
,hasMany
和belongsToMany
.我更喜欢使用
exists
方法:RepairItem::find($id)->option()->exists()
检查相关模型是否存在 . 它在Laravel 5.2上运行良好
在 Php 7.1 之后,接受的答案将不适用于所有类型的关系 .
因为根据类型的关系,Eloquent将返回
Collection
,Model
或Null
. 在 Php 7.1count(null)
将抛出error
.因此,要检查关系是否存在,您可以使用:
对于单身关系:例如
hasOne
和belongsTo
对于多个关系:例如:
hasMany
和belongsToMany
不确定这是否在Laravel 5中有所改变,但使用
count($data->$relation)
的接受答案对我不起作用,因为访问关系属性的行为导致它被加载 .最后,一个直截了当的
isset($data->$relation)
为我做了伎俩 .您可以在模型对象上使用relationLoaded方法 . 这节省了我的培根,希望它可以帮助别人 . 当我在Laracasts问同样的问题时,我就是given this suggestion .
正如Hemerson Varela在Php 7.1中已经说过
count(null)
将抛出error
和hasOne
如果没有行则返回null
. 由于你有hasOne
关系,我会使用empty
方法来检查:你说你想检查关系是否已经存在,所以你可以做
update
或create
. 但是,由于updateOrCreate方法,这不是必需的 .这样做: