如何正确的检测数据模型是否存在
问题
Laravel 开发中,在检测 Eloquent 数据关系模型 是否存在时,我们经常会犯以下的错误。
以下是错误的代码演示:
// 判断是否有关联数据
if ($model->relation){
... 注意这是错误的演示
}
推荐方案
推荐的做法是使用 count 来判断:
// 判断是否有关联数据
if ( count($model->relation) ){
... 如果存在的话
}
因为 Eloquent 数据模型(Eloquent Model) 和 集合 (Collection)都实现了 ArrayAccess,所以使用 count 是通用的。
为什么不能使用 $model->relation
来判断?
接下来分「单一对应关系」和「多个对应关系」来讲解。
单一对应关系(返回数据模型 Model)
单一对应关系指的是使用以下关键词定义的关联模型:
- hasOne
- belongsTo
- morphTo
- morphOne
在单一对应关系下,使用 $model->relation
来做判断会有以下逻辑:
// 在没有对应模型的情况下
$model->relation; // 返回 null,在 if 判断里面等于 false
count($model->relation); // 返回 0,在 if 判断里面等于 false
// 存在对应模型的情况下
$model->relation; // Eloquent 数据模型(Model),在 if 判断里面等于 true
count($model->relation); // 1 ,在 if 判断里面等于 true
从上面的实例代码中可看出直接使用 $model->relation
与 count
函数来做判断结果一致。
多个对应关系(返回集合)
多个对应关系指的是使用以下关键词定义的关联模型:
- hasMany
- belongsToMany
- morphMany
- morphToMany
- morphedByMany
在多个对应关系下,使用 $model->relation
来做判断会有以下逻辑:
// 没有对应模型的情况下
$model->relation; // 空集合,在 if 判断里面等于 true <--- 注意这里!!!
count($model->relation); // 0,在 if 判断里面等于 false
// 存在对应模型的情况下
$model->relation; // 非空集合,在 if 判断里面等于 true
count($model->relation); // int > 0 ,在 if 判断里面等于 true
这里的问题出在当没有对应模型时,$model->relation
会返回「空集合对象」在 if
判断里面等于 true
,使用 count 可以避免此问题。
empty() 和 集合的 ->count(), ->isEmpty() 方法
你也许在项目中使用过 empty()
和 集合的 count()
、`isEmpty() 方法来判断数据模型是否存在,也许你没有错,不过,建议使用 count 来判断,原因如下:
- empty() 对于空集合对象的话,还是会返回 true;
- ->count() 属于集合专属的方法,无法对 Model 使用,只能在多个对应关系下使用;
- ->isEmpty() 同上;
PHP 内置的 count 函数对以上所有情况都通杀,不论是单一、多个对应关系,不论是数组、集合,还是 Eloquent 数据模型。
Summer
@zhuzhichao :+1: 。
还是觉得使用 count 通用,需要记的东西少点,减少犯错的可能性。
wow 好细节,想起之前写的代码。。。
收获大
PHP 7.1 某一个子版本前后,出现了更新,新版本的 count 函数会报错,提示参数必须 countable.
php7.2 count 报错..
由于 PHP 7.2 和 8.0 陆续提高了
count()
参数为 非 countable 类型时的报错等级,这里可以用blank()
替代count()