是否存在相关模型的 Laravel 检查

我有一个雄辩模式,其中有一个相关的模式:

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>是我正在寻找的代码。

246955 次浏览

Php 7.2 + 中,你不能在关系对象上使用 count,所以没有一个适合所有关系的方法。使用查询方法代替下面提供的@tremby:

$model->relation()->exists()

适用于所有关系类型(7.2版本)的通用解决方案:

if (count($model->relation))
{
// exists
}

这将适用于每个关系,因为动态属性返回 ModelCollection

它是这样的:

单一关系: 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

关系对象将未知的方法调用传递给 雄辩的查询生成器雄辩的查询生成器被设置为只选择相关对象。该 Builder 依次将未知方法调用传递给基础 查询生成器它的

这意味着您可以直接从关系对象使用 exists()count()方法:

$model->relation()->exists(); // bool: true if there is at least one row
$model->relation()->count(); // int: number of related rows

请注意,relation后面的括号: ->relation()是一个函数调用(获取关系对象) ,而 ->relation是 Laravel 为您设置的一个神奇的属性 getter (获取相关的对象/对象)。

在关系对象上使用 count方法(即使用括号)比执行 $model->relation->count()count($model->relation)要快得多(除非关系已经被迫加载) ,因为它运行一个计数查询,而不是从数据库中提取任何相关对象的所有数据,只是为了计数它们。同样,使用 exists也不需要提取模型数据。

exists()count()都适用于我试过的所有关系类型,所以至少适用于 belongsTohasOnehasManybelongsToMany

不确定这在 Laravel 5中是否已经改变,但是使用 count($data->$relation)接受的答案对我来说不起作用,因为访问关系属性的行为导致它被加载。

最后,一个简单的 isset($data->$relation)帮了我大忙。

我更喜欢使用 exists方法:

RepairItem::find($id)->option()->exists()

检查相关模型是否存在,在 Laravel 5.2上运行良好

您可以对模型对象使用 有感情方法。这救了我的命,希望能帮到别人。当我在 Laracast 上问同样的问题时,我是 考虑到这个建议

Php 7.1之后,接受的答案不适用于所有类型的关系。

因为根据类型的关系,雄辩将返回一个 Collection,一个 ModelNull。在 Php 7.1中,count(null)会抛出一个 error

因此,要检查关系是否存在,可以使用:

对于单身关系: 例如 hasOnebelongsTo

if(!is_null($model->relation)) {
....
}

对于多重关系: 例如: hasManybelongsToMany

if ($model->relation->isNotEmpty()) {
....
}

正如 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();
};

但这是多余的。没有必要检查关系是否存在,以确定是否应该执行 updatecreate调用。只需使用 UpdateOrCreate方法。这等同于以上所述:

$model = RepairItem::find($id);
if (!empty($temp = $request->input('option'))) {
$model->option()
->updateOrCreate(['repair_item_id' => $model->id],
['option' => $temp]);
}

当我将 PHP 版本更新到7.2 + 时,由于 count ($x)函数使用不当,我不得不完全重构代码。这是一个真正的痛苦,它也非常可怕,因为有数以百计的用法,在不同的情况下,没有一个规则适合所有。.

我重构所有东西时遵循的规则,例如:

$x = Auth: : user ()-> posts-> find (6) ; (使用-> find ()检查 user 是否有 post id = 6)

[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x) { return 'Found'; }

$x = Auth: : user ()-> profile-> department; (检查 profile 是否有一些 department,可以有许多 department)

[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }

$x = Auth: : user ()-> profile-> get () ; (在使用-> get ()之后检查 user 是否有一个 profile)

[FAILS] if(count($x)) { return 'Found'; }
[GOOD] if($x->count()) { return 'Found'; }

希望这个可以帮助,甚至5年后的问题一直在问,这个堆栈溢出的职位已经帮助了我很多!

如果您使用模型类并使用 EloquentORM,那么创建一个新方法并返回 bool 数据

public function hasPosts(): bool
{
return $this->posts()->exists();
}

我用于单一关系: hasOnebelongsTomorphs

if($model->relation){
....
}

因为如果条件为 null,那么它就是 false。

对于多种关系: hasManybelongsToManymorphs

if ($model->relation->isNotEmpty()) {
....
}