Laravel 5.6 - Проблемы с использованием Eloquent для возврата самой последней даты в поле datetime связанной таблицы - PullRequest
0 голосов
/ 26 сентября 2018

У меня две таблицы: пациенты и приложения (назначения).Существует один: много отношений пациента: ок.Моя цель состоит в том, чтобы возвратить набор пациентов и из даты последнего и следующего посещения пациента.

Проблема / Проблема

Я получаю противоречивые результаты.Я просеял данные так, чтобы у каждого пациента были назначения в прошлом и будущем, но когда я использую Eloquent для запроса (см. «Контроллер» ниже), я не получаю «lastappt».Если я изменяю запрос для поиска по идентификатору пациента, я получаю 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, даже если база данных имела приложения в прошлом.Однако следующий запрос работает (как я и ожидал) и возвращает запись пациента с lastappt и nextappt.

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

Любая помощь будет принята с благодарностью и заранее благодарим вас!

1 Ответ

0 голосов
/ 26 сентября 2018

Вы можете использовать:

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;

Конечно, в трех строчках выше следует предположить, что lastappt или nextappt могут бытьnull, так что вы можете использовать optional helper:

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();
...