【问题标题】:Filter Events which has some specific status过滤具有某些特定状态的事件
【发布时间】:2019-06-07 10:40:56
【问题描述】:

我正在尝试查询我的数据库以仅获取具有“已确认”状态的行,但状态保存在日志表中,而不是事件中,我需要在其中执行查询。 logs 表存储所有手术状态,ID 为 1 的手术的当前状态是插入 surgery_id 1 的最后一行。如何获取所有手术状态为CONFIRMED 的事件?

这是我的数据库结构:

 Surgery           Events              Log
    id               id                id
patient_id       surgery_id         surgery_id
                                    status_id

我正在使用 laravel v5.7.28,带有 postgresql 数据库。

surgery 型号上:

public function status()
{
    return $this->hasMany(Cirurgia_log::class)
        ->orderBy('created_at', 'desc');
}

如果我使用以下代码,而不是第一个,我可以成功获得最后一个状态:

public function status()
{
    return $this->hasMany(Log::class)
        ->orderBy('created_at', 'desc')->first();
}

但是,有了这个,我不能使用 whereHas 函数。

surgery 关系在 Events 模型上定义:

public function surgery()
{
    return $this->belongsTo(Surgery::class, 'surgery_id');
}

我尝试使用下面的代码,但是,使用这个代码,如果手术已确认但现在已取消,则与该手术相对应的事件也将返回,一旦该手术已在某个时间得到确认。

Events::whereHas('surgery.status', function ($query){
    $query->where('status_id', env('CONFIRMED'));
})->get();

总结起来,我只需要获取与该事件相关的手术具有 CONFIRMED 状态的事件。

【问题讨论】:

    标签: laravel relationship laravel-5.7


    【解决方案1】:

    您可以简单地将HasManyHasOne 交换:

    public function status()
    {
        return $this->hasOne(Log::class)
            ->orderBy('created_at', 'desc');
    }
    

    status 作为一个词的问题在于它是模棱两可的。单数和复数都是一样的,这使得我们很难确定我们是在谈论一个还是多个。所以我可能会选择 latestStatus()HasOnestatus()HasMany 来覆盖两者。

    public function status()
    {
        return $this->hasMany(Log::class)
            ->orderBy('created_at', 'desc');
    }
    
    public function latestStatus()
    {
        return $this->hasOne(Log::class)
            ->orderBy('created_at', 'desc');
    }
    

    【讨论】:

    • 我用你的函数替换了我的函数,使用hasOne,但它仍然返回当前状态未确认的事件。同样的问题
    • 能否将生成的 SQL 查询添加到您的问题中?如果您不使用显示已执行 SQL 查询的调试工具,您可以在查询之前使用\DB::enableQueryLog() 启用 SQL 查询日志,并在查询执行后使用\var_dump(DB::getQueryLog()) 转储查询日志。跨度>
    • 当然。这是生成的脚本: array(1) { [0]=> array(3) { ["query"]=> string(341) "select * from "events" where exists (select * from "surgeries" where " events"."surgery_id" = "surgeries"."id" 并且存在(从 "logs" 中选择 *,其中 "surgeries"."id" = "logs"."surgery_id" 和 "status_id" = ? 和 "logs"。 "deleted_at" 为空) 和 "surgeries"."deleted_at" 为空) 和 "events"."deleted_at" 为空" ["bindings"]=> array(1) { [0]=> string(2) " 17" } ["时间"]=> 浮点数(22.49)
    • 嗯,你确定你的代码和我建议的一样吗?我完全想念order by
    • 是的,我有你建议的 latestStatus 函数。
    【解决方案2】:

    我用下面的代码解决了:

    public function scopeConfirmedMaterials()
    {
        return $this->whereHas('surgery.latestStatus', function ($query){
            $query->where('status_id', env('CONFIRMED'));
        })->get()
            ->filter(function ($event){
                return $event->surgery
                    ->latestStatus
                    ->status_id == env('CONFIRMED');
            });
    }
    

    事件模型上的surgery 关系:

    public function surgery()
    {
        return $this->belongsTo(Surgery::class);
    }
    

    latestStatus 关系,关于手术模型:

    public function latestStatus()
    {
        return $this->hasOne(Log::class)
            ->orderBy('created_at', 'desc');
    }
    

    EventController:

    public function getEvent(){
        return response()->json(
            'data' => Events::confirmedMaterials();
        );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-29
      • 2019-04-18
      • 1970-01-01
      • 2016-02-03
      • 1970-01-01
      • 1970-01-01
      • 2018-01-09
      相关资源
      最近更新 更多