我有一个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>
是我要找的代码。
答案 0 :(得分:154)
在 php 7.2 + 中,您无法在关系对象上使用count
,因此对于所有关系都没有一个通用的方法。使用查询方法改为@tremby,如下所示:
$model->relation()->exists()
处理所有关系类型的通用解决方案( pre php 7.2 ):
if (count($model->relation))
{
// exists
}
这将适用于每个关系,因为动态属性返回Model
或Collection
。两者都实现ArrayAccess
。
所以它是这样的:
单一关系: hasOne
/ belongsTo
/ morphTo
/ morphOne
// no related model
$model->relation; // null
count($model->relation); // 0 evaluates to false
// there is one
$model->relation; // Eloquent Model
count($model->relation); // 1 evaluates to true
对多关系: hasMany
/ belongsToMany
/ morphMany
/ morphToMany
/ morphedByMany
// no related collection
$model->relation; // Collection with 0 items evaluates to true
count($model->relation); // 0 evaluates to false
// there are related models
$model->relation; // Collection with 1 or more items, evaluates to true as well
count($model->relation); // int > 0 that evaluates to true
答案 1 :(得分:61)
Relation object将未知方法调用传递给Eloquent query Builder,query Builder设置为仅选择相关对象。该Builder又将未知方法调用传递给其底层exists()
。
这意味着您可以直接从关系对象中使用count()
或{{3}}方法:
$model->relation()->exists(); // bool: true if there is at least one row
$model->relation()->count(); // int: number of related rows
注意relation
之后的括号:->relation()
是一个函数调用(获取关系对象),而不是->relation
,这是一个由Laravel为你设置的魔法属性获取器(获取)相关的对象/对象)。
在关系对象上使用count
方法(即使用括号)将比执行$model->relation->count()
或count($model->relation)
快得多(除非关系已经急切加载) )因为它运行计数查询而不是从数据库中提取任何相关对象的所有数据,只是为了计算它们。同样,使用exists
也不需要提取模型数据。
exists()
和count()
都适用于我尝试过的所有关系类型,因此至少belongsTo
,hasOne
,hasMany
和{ {1}}。
答案 2 :(得分:16)
我更喜欢使用exists
方法:
RepairItem::find($id)->option()->exists()
检查相关模型是否存在。它在Laravel 5.2上运行良好
答案 3 :(得分:8)
在 Php 7.1 之后,接受的答案对所有类型的关系都不起作用。
因为根据类型的关系,Eloquent将返回QQmlApplicationEngine
,Collection
或Model
。在 Php 7.1 Null
中会抛出count(null)
。
因此,要检查关系是否存在,您可以使用:
对于单身关系:例如error
和hasOne
belongsTo
对于多重关系:例如:if(!is_null($model->relation)) {
....
}
和hasMany
belongsToMany
答案 4 :(得分:4)
不确定Laravel 5中是否已更改,但使用count($data->$relation)
接受的答案对我不起作用,因为访问关系属性的行为导致它被加载。
最后,一个直截了当的isset($data->$relation)
为我做了诀窍。
答案 5 :(得分:2)
您可以在模型对象上使用relationLoaded方法。这节省了我的培根,希望它可以帮助别人。当我在Laracasts上问同样的问题时,我才given this suggestion。
答案 6 :(得分:2)
正如Hemerson Varela在Php 7.1 count(null)
已经说过的那样,如果不存在行,则会error
和hasOne
返回null
。由于您有hasOne
关系,我会使用empty
方法检查:
$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
$option = $model->option;
if(empty($option)){
$option = $model->option()->create();
}
$option->someAttribute = temp;
$option->save();
};
但这是多余的。无需检查关系是否存在,以确定您是应该进行update
还是create
来电。只需使用updateOrCreate方法即可。这相当于上面的内容:
$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
$model->option()
->updateOrCreate(['repair_item_id' => $model->id],
['option' => $temp]);
}
答案 7 :(得分:1)
由于将count($ x)函数的用法错误,当我将PHP版本更新到7.2+时,我不得不完全重构代码。这是一种真正的痛苦,而且也非常可怕,因为在不同的情况下有成百上千种用法,并且没有一项规则能适合所有人。
我遵循的规则来重构一切,例如:
$ x = Auth :: user()-> posts-> find(6); (使用-> find()检查用户是否有帖子id = 6)
[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x) { return 'Found'; }
$ x = Auth :: user()->个人资料->部门; (检查个人资料是否有部门,可以有很多部门)
[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }
$ x = Auth :: user()-> profile-> get(); (使用-> get()后检查用户是否具有个人资料)
[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }
希望这可以帮到忙,即使在问了问题5年之后,这篇stackoverflow帖子也对我有很大帮助!
答案 8 :(得分:0)
如果使用模型类并使用 Eloquent ORM,则创建一个新方法并返回 bool 数据。喜欢
public function hasPosts(): bool
{
return $this->posts()->exists();
}