Laravel雄辩的存取器奇怪问题

时间:2019-03-06 07:12:47

标签: laravel eloquent

Laravel Version: 5.6.39
PHP Version: 7.1.19
Database Driver & Version: mysql 5.6.43

说明:

当我在模型访问器中链接where和orWhere来计算相关模型时,我得到错误的结果,这是我的查询。计数返回奇怪的结果,而没有按调用事件ID进行过滤,

class Event extends Model
{
    protected $table = 'events';
    public function registrations()
    {
        return $this->hasMany('App\Components\Event\Models\Registration','event_id','id');
    }

    public function getSeatsBookedAttribute()
    {
        return $this->registrations()          
            ->where('reg_status','=','Confirmed')
            ->orWhere('reg_status','=','Reserved')
            ->count();
    }
}

复制步骤:

以下查询返回了我期望的结果,但是据我所知,如果我没记错的话,第一个查询应该返回相同的结果,所以我认为这是一个潜在的错误。

class Event extends Model
{
    public function getSeatsBookedAttribute()
    {
        return $this->registrations()          
             ->whereIn('reg_status', ['Confirmed', 'Reserved'])
            ->count();
    }

}


class Event extends Model
{
    public function getSeatsBookedAttribute()
    {
        return $this->registrations()          
          ->where(function($query){
                $query->where('reg_status','Confirmed')
                    ->orWhere('reg_status','Reserved');
           })
            ->count();
    }

}

这是查询转储,

这是我未明确分组的查询。

"select count(*) as aggregate from events_registration where (events_registration.event_id = ? and events_registration.event_id is not null and reg_status = ? or reg_status = ?) and events_registration.deleted_at is null "

这是我明确对其进行分组时的查询

select count(*) as aggregate from events_registration where events_registration.event_id = ? and events_registration.event_id is not null and (reg_status = ? or reg_status = ?) and events_registration.deleted_at is null 

1 个答案:

答案 0 :(得分:1)

发生这种情况的原因是因为您要链接where()orWhere()。您在幕后看不到的是where event_id = :event_id应用于您的查询。您最终得到的查询看起来像这样:

select * from registrations where event_id = :event_id and reg_status = 'Confirmed' or reg_status = 'Reserved'

在普通SQL中,您希望将最后2个条件放在括号中。对于Eloquent,您需要执行以下操作:

return $this->registrations()->where(function ($query) {
   $query->where('reg_status', 'Confirmed')
      ->orWhere('reg_status', 'Reserved');
});

您可以在这些链上链接toSql()方法,以查看区别。请注意,在这种情况下,我认为whereIn()是在语义上正确的事情。

尽管如此,口才可以为您解决;在口才关系文档的Querying Relations部分中向下滚动至“计算相关模型”:

$posts = App\Event::withCount([
    'registrations as seats_booked_count' => function ($query) {
            $query->where('reg_status','Confirmed')
                ->orWhere('reg_status','Reserved');
    }
])->get();