使用Eloquent选择空字符串或null值的行

22

我有一个像这样的代码:$user->albums()->where('col', NULL),它能正常工作。然后我尝试使用$user->albums()->where('col', NULL)->or_where('col', '') 来扩展它以匹配空字符串,但是它并不起作用。

另外,我在这篇帖子中看到可以使用where_null('col'),但是它并没有起作用,并且文档中也没有提到。是否有简单的方法来选择空或NULL的col呢?


给未来的用户一个提示,解决方案是使用 whereNull('column'),你可以在 https://laravel.com/docs/5.7/queries#unions 中看到。 - Marcelo Agimóvel
6个回答

66

尝试在第二个条件中使用orWhereNull

$users = DB::table('users')
        ->where('col', '=', '')
        ->orWhereNull('col')
        ->get();

或者如果您在查询中有多个条件,则必须将两个条件包含在闭包内:

    $users = DB::table('users')
             ->where(function(\Illuminate\Database\Eloquent\Builder $query) {
                $query->where('col', '')->orWhereNull('col');
            })
            ->where('col2','val2')
            ->get();



5
如果我们有多个条件,我们该如何更改 where 函数? - Nevermore
5
使用闭包:DB::table('users')->where(function($query) { $query->where(...)->orWhere(...)->orWhere(...); })->where(...)->where(...)->get();。这将在生成的SQL语句中将基于闭包的条件封装在括号中。 - Soulriser
1
添加模型作用域方法可以使使用闭包更加容易: 用法: $model->whereIsEmpty($column1)->whereIsEmpty($column2); 实现: public function scopeWhereIsEmpty($query, $column) { return $query->where( function ($query) use ($column) { $query->where($column, '')->orWhereNull($column); } ); } - JBB

3
这个怎么样?
$user->albums()->whereRaw("NOT col > ''")

这种方式可以同时检查两个条件


2
尝试这个查询:

$users = DB::table('users')
        ->whereRaw('col = "" OR col IS NULL')
        ->get();

1
我始终鼓励使用最常用的 Laravel 函数创建查询。因此,您必须记住两件事:
  • 算法。key1 = value1 AND key2 = value2 OR key3 = value3。请注意优先级,因为在我举例的方式中,主要是 OR 而不是 AND 带有 OR。
  • 使用 where()、whereIn()、whereNull 和闭包,而不是 whereRaw()。whereRaw 比我提到的其他任何函数都使用更多内存。

因此,总结一下您的答案:

OR 条件

$users = DB::table('users')
        ->where('col', '=', '')
        ->orWhere('col','=','')
        ->whereNull('col')
        ->get();

AND 和 OR 条件

$users = DB::table('users')
->where(function($query) { $query->where('col','=','')->orWhere('col','=','')->whereNull('col'); })
->where('col','=','')
->get();

1
以下解决方案已在LARAVEL 9上进行了测试。解决方案是将以下代码添加到App\Providers\AppServiceProvider中:
class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        ///...
        Builder::macro('whereNullOrEmpty', function ($field) {
            return $this->where(function ($query) use ($field) {
                return $query->where($field, '=', null)->orWhere($field, '=', '');
            });
        });

        Builder::macro('whereNotNullOrEmpty', function ($field) {
            return $this->where(function ($query) use ($field) {
                return $query->where($field, '<>', null)->where($field, '<>', '');
            });
        });
    }
    //...
}

然后像这样调用它:

if($nullOrEmpty){
    $builder->whereNullOrEmpty('col');
}else{
    $builder->whereNotNullOrEmpty('col');
}

你必须调用两个命令:

where($field, '<>', null);
where($field, '<>', '');

因为MySQL在处理空字符串和NULL值时与PHP不同,所以您还需要使用闭包将这两个命令封装起来,告诉Eloquent将生成的代码放在括号中并隔离MySQL代码:
(where col = null or where col = '')

-5

不太确定,但这可能有效:

$user->albums()->where_in('col', array(NULL,''));

5
NULL不能使用=操作符进行比较,所以这不起作用。此外,方法的名称是whereIn而不是where_in。应该测试过它,而不是写下“不确定,但这可能起作用”... - jsphpl
2
@jsphpl 你的评论当然是正确的,但需要注意的是,如果你在 Collection 对象上而不是查询构造器上运行 whereIn('col', [null, '']),它是会工作的。例如:$user->albums->whereIn('col', [null,'']);。请注意使用了魔术关系属性 albums,它返回一个集合,而不是返回查询构建器实例的 albums() - Soulriser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接