Laravel 5.6-使用Eloquent在相关表的日期时间字段中返回最新日期的问题

时间:2018-09-26 17:24:26

标签: php laravel laravel-5 eloquent laravel-5.6

我有两个表:患者和预约(预约)。有一个一对多的关系,病人:appt。我的目标是返回患者集合,并从该关系中返回患者的上次约会和下一次约会的日期。

问题/问题

我得到不一致的结果。我已经播种了数据,以便每个患者在过去和将来都有约会,但是当我使用Eloquent进行查询时(请参见下面的“控制器”),我不会得到“ lastappt”。如果我修改查询以按患者的ID进行搜索,我会得到lastappt。

“患者”模型

class Patient extends Model
{
    ...
    public function appts()
    {
        return $this->hasMany('App\Models\Appt');
    }
    public function lastappt()
    {
        $now = Carbon::now();
        return $this
            ->hasMany('App\Models\Appt')
            ->select(['id', 'patient_id', 'appt_date_time'])
            ->where('appt_date_time', '<', $now)
            ->orderBy('appt_date_time', 'desc')
            ->take(1);
    }
    public function nextappt()
    {
        $now = Carbon::now();
        return $this
            ->hasMany('App\Models\Appt')
            ->select(['id', 'patient_id', 'appt_date_time'])
            ->where('appt_date_time', '>', $now)
            ->orderBy('appt_date_time', 'asc')
            ->take(1);
    }
}    

“ Appts”迁移

Schema::create('appts', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('patient_id')->unsigned();
    $table->integer('hospital_id')->unsigned();
    ...
    $table->datetime('appt_date_time')->nullable();
    ...
    $table->timestamps();
    $table->index(['patient_id', 'hospital_id', 'appt_date_time']);
    $table->foreign('patient_id')
        ->references('id')->on('patients')
        ->onDelete('cascade');
});

控制器

$currPatientCollection = Patient::with('lastappt')
    ->with('nextappt')
    ->where('office_id', $user->office_id)
    ->where('current_patient', true)
    ->orderBy('last_name')
    ->orderBy('first_name')
    ->get();

这将仅返回nextappt,即使数据库过去具有appts。但是,以下查询有效(正如我所预期的那样),并返回带有lastappt和nextappt的患者记录。

$currPatientCollection = Patient::with('lastappt')
    ->with('nextappt')
    ->where('id', 1)
    ->where('current_patient', true)
    ->orderBy('last_name')
    ->orderBy('first_name')
    ->get();

任何帮助将不胜感激,谢谢您!

1 个答案:

答案 0 :(得分:0)

您可以使用:

public function lastappt()
{
    $now = Carbon::now();
    return $this
        ->hasOne('App\Models\Appt')
        ->select(['id', 'patient_id', 'appt_date_time'])
        ->where('appt_date_time', '<', $now->toDateTimeString())
        ->orderBy('appt_date_time', 'desc')
        ->groupBy('patient_id');
}

public function nextappt()
{
    $now = Carbon::now();
    return $this
        ->hasOne('App\Models\Appt')
        ->select(['id', 'patient_id', 'appt_date_time'])
        ->where('appt_date_time', '>', $now->toDateTimeString())
        ->orderBy('appt_date_time', 'asc')
        ->groupBy('patient_id');
}

现在您可以使用:

$patient = Patient::find($someId);
echo $patient->lastappt->appt_date_time;
echo $patient->nextappt->appt_date_time;

当然,在以上3行中,您应该假设lastapptnextappt可能为空,因此您可以使用optional助手:

echo optional($patient->lastappt)->appt_date_time;
echo optional($patient->nextappt)->appt_date_time;

当然,当您有多个患者时,您应该渴望加载这些关系以避免n + 1个查询问题:

$patients = Patient::with('lastappt', 'nextappt')->whereIn('id', $someIds)->get();