Как создать трехсторонний пивот с помощью Eloquent ORM

Очень новичок в Laravel, но мне нравится то, что я вижу до сих пор.

Я работаю над приложением, в котором клиенты посещают сеансы, а сеансы могут посещаться многими клиентами. В дополнение к этому, клиенты могут также выполнять оценки на сессиях, которые они посещают, на индивидуальной основе (т.е. один клиент = одна оценка). Также стоит отметить, что они могут или не могут сдавать экзамен.

Лучший способ объяснить это ...

Как создать трехсторонний пивот с помощью Eloquent ORM

Также важно отметить, что данные должны быть согласованными - завершенная оценка должна выполняться в сеансе, в котором присутствовал клиент. то есть клиент должен присутствовать на сеансе - то же самое верно и в обратном случае - клиент не может завершить и оценить сеанс, на котором он или она не присутствовал.

Это скорее попытка обдумать лучшую структуру для этого и использовать Eloquent ORM в Laravel. Я знаю, что могу найти рабочее решение, которое определенно будет искажено и беспорядочно, но я бы предпочел знать правильный способ.

Какой-то подходящий код:

class Client extends Model
{
    public function sessions()
    {
        return $this->hasMany('App\Session');
    }

    public function assessments()
    {
        return $this->hasMany('App\Assessment');
    }
}

class Session extends Model
{
    public function clients()
    {
        return $this->hasMany('App\Client');
    }

    public function assessments()
    {
        return $this->hasMany('App\Assessment');
    }
}

//This is where I am having difficulty...

class Assessment extends Model
{
    public function client()
    {
        return $this->hasOne('App\Client');
    }

    public function session()
    {
        return $this->hasOne('App\Session');
    }
}

Проблема, с которой я сталкиваюсь, заключается в том, как создать эти трехсторонние отношения между «клиентом», «сеансом» и «оценкой» таким образом, чтобы обеспечить соблюдение целостности и доступность.

Я думал о нескольких вещах:

  1. Создайте сводную таблицу client_session, добавьте в нее дополнительное поле под названием Assessment_id и используйте его для привязки оценки к уникальной комбинации клиента и сеанса. Я не уверен, как (или даже если это возможно) определить такое отношение к таблице без модели.

  2. Используйте «Оценки» в качестве сводной таблицы. Мне не очень нравится эта идея, поскольку возможно, что оценки не проводятся, но мне все еще нужны эти отношения между клиентом и сеансом, и хранить это в «Оценках» кажется неправильным.

  3. Создайте отдельную таблицу «Посещаемость» и связанный с ней «сводный класс», т.е. расширяет сводную, а не модель - действительно не уверен в этом!

Мне удалось структурировать данные с помощью простых таблиц и использовать ВНУТРЕННИЕ СОЕДИНЕНИЯ вне Laravel, но я хотел понять, как лучше всего реализовать это с помощью Eloquent.

Я также видел отношение ownToMany () с использованием Pivot (т.е. расширяет Pivot, а не Model) или отношения hasManyThrough ().

Я также видел https://github.com/jarektkaczyk/Eloquent-triple-pivot, но он не поддерживался в течение 4 лет, поэтому я предполагаю, что это можно сделать с любыми кораблями с Eloquent / Laravel.

Любая помощь, очень признательна!

**** ОБНОВИТЬ ****

Хорошо, так что @barghouthi сильно помог мне с моим пониманием. В настоящее время мои модели выглядят следующим образом:

class Client extends Model
{
    public function sessions()
    {
        return $this->belongsToMany('App\Session', 'attendance')->using('App\Attendance');
    }
}

class Session extends Model
{
    public function clients()
    {
        return $this->belongsToMany('App\Client', 'attendance')->using('App\Attendance');
    }
}

class Attendance extends Pivot
{
    public function client()
    {
        return $this->belongsTo('App\Client', 'attendance');
    }

    public function session()
    {
        return $this->belongsTo('App\Session', 'attendance');
    }

    public function assessment()
    {
        return $this->hasMany('App\Assessment','attendance');
    }
}

class Assessment extends Model
{
    public function attendance()
    {
        return $this->belongsTo('App\Attendance');
    }

    public function client()
    {
        // for now
        return $this->attendance()->client();
    }

    public function session()
    {
        // for now
        return $this->attendance()->session();
    }
}

Я намеренно переименовал сводную таблицу, чтобы она отражала класс Pivot.

Я поместил фиктивные данные в таблицу посещаемости, например:

Как создать трехсторонний пивот с помощью Eloquent ORM

Когда я запрашиваю клиентские сеансы для идентификатора клиента 1, он возвращает четыре записи, а не две. Четыре - это правильно с точки зрения таблицы посещаемости, но я хотел бы, чтобы возвращались только две записи - то есть сеансы.

**** ОБНОВИТЬ

Хорошо, так что я много учусь, а я не совсем там. Это мое текущее решение:

class Client extends Model
{
    public function sessions()
    {
        return $this->belongsToMany('App\Session', 'attendance')->using('App\Attendance')->distinct('session_id');
    }

    public function assessments()
    {
        return $this->hasManyThrough('\App\Assessment', '\App\Attendance', 'client_id', 'id');
    }
}

class Session extends Model
{
    public function clients()
    {
        return $this->belongsToMany('App\Client', 'attendance')->using('App\Attendance')->distinct('client_id');
    }

    public function assessments()
    {
        return $this->hasManyThrough('\App\Assessment', '\App\Attendance', 'session_id', 'id');
    }
}

class Assessment extends Model
{   
    public function client()
    {
        return $this->belongsToMany('\App\Client', 'attendance', 'id', 'client_id')->using('\App\Attendance');
    }

    public function session()
    {
        return $this->belongsToMany('\App\Session', 'attendance', 'id', 'session_id')->using('\App\Attendance');
    }
}

В таблице посещаемости просто есть id, client_id и session_id. Я решил, что нет необходимости в Assessment_id, поскольку существует взаимосвязь один к одному (то есть оценка (оценки) может или не выполняться клиентом на конкретном сеансе)

class Attendance extends Pivot
{
    public function clients()
    {
        return $this->belongsTo('App\Client', 'attendance');
    }

    public function sessions()
    {
        return $this->belongsTo('App\Session', 'attendance');
    }

    public function assessments()
    {
        return $this->belongsTo('App\Assessment','attendance');
    }
}

По большей части это, кажется, решает проблему. Если я попытаюсь вызвать

$assessment->client->id

Получаю следующее:

Property [id] does not exist on this collection instance.

Это означает, что мои отношения в оценке не совсем правильные, если я хочу прочитать свойства связанных элементов.

Когда я использую

$assessment->client

На выходе

[{"id":1,"created_at":"2018-10-24 19:15:41","updated_at":"2018-10-24 19:15:41","date_of_birth":"26 Sep 1974","gender":1,"initial_contact_date":"2013-05-01","initial_session_offered_date":"2002-07-06","contact_from":1,"presentation":"Vitae qui et nesciunt iste autem numquam earum. Illo repudiandae deleniti vel nesciunt non iure. Sunt est nemo ut excepturi illum temporibus.","counsellor_id":1,"pivot":{"id":1,"client_id":1}}]

Так что, думаю, я близок.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
0
115
1

Ответы 1

поэтому, если у вас есть таблица client_session или attendance с id, client_id, session_id, и вы используете эту таблицу в качестве внешнего ключа в таблице оценок.

Дело в том, что сводная таблица может быть моделью

см. Многие ко многим: Определение пользовательских моделей промежуточных таблиц

class Client extends Model
{
    public function sessions()
    {
        // using intermediate model
        return $this->belongsToMany('App\Session')->using('App\Attendance');
    }
}

class Session extends Model
{
    public function clients()
    {
        // using intermediate model
        return $this->belongsToMany('App\Session')->using('App\Attendance');
    }
}


class Attendance extends Pivot
{
    public function clients()
    {
        return $this->belongsTo('App\Client');
    }

    public function session()
    {
        return $this->belongsTo('App\Session');
    }

    public function Assessments()
    {
        return $this->hasMany('App\Assessment');
    }

}



class Assessment extends Model
{
    public function attendance()
    {
        return $this->belongsTo('App\Attendance');
    }

    public function client()
    {
        // for now
        return $this->attendance()->client();
    }

    public function session()
    {
        // for now
        return $this->attendance()->client();
    }
}

Таким образом, вы не сможете пройти оценку без присутствия и посещаемость может иметь множество оценок.

Оценка будет выглядеть так:

id, attendance_id: относится к клиенту и сеансам

Это определенно поставило меня на верный путь. Спасибо. Одна (надеюсь, последняя!) Вещь, с которой я борюсь, - это то, что клиент может выполнить две оценки за один сеанс. Проблема здесь в том, что когда дело доходит до извлечения сеансов, он предоставляет две записи, то есть Record #1: client_id:1 session_id:1 assessment_id:1 Record #2: client_id:1 session_id:1 assessment_id:2. Данные являются надежными. Мне просто нужен способ отфильтровать это, чтобы он извлекал только отдельные сеансы, а не каждую запись «посещаемости».

Zakalwe 23.10.2018 14:39

Это не проблема, оценка относится к посещаемости, но по посещаемости может быть несколько оценок. на самом деле в моем ответе есть ошибка. Оценка - это нормальная модель (расширяет Модель) Сейчас исправлю

zjbarg 23.10.2018 14:46

Я заметил проблему с опорой, которая означает, что часть этого происходит! Что касается проблемы в моем последнем комментарии, это потому, что связь возвращает данные из таблицы «посещаемости», а не из конечной таблицы «оценки». Данные верны, но мне это нужно, чтобы вытащить DISTINCT записи (а-ля SQL), чтобы они просто давали мне сеансы - в отличие от записи для каждой уникальной комбинации.

Zakalwe 23.10.2018 19:40

если вы приведете несколько примеров, будет легче понять !.

zjbarg 23.10.2018 19:51

Зачем вам иметь два экземпляра посещаемости для одного и того же клиента и сеанса?

zjbarg 23.10.2018 23:42

Потому что клиент может пройти более одного экзамена за сеанс.

Zakalwe 24.10.2018 19:10

так что у вас будет таблица оценок, например> id, attendance_id, assessment_details. вы просто добавите сюда еще одну запись с тем же посещаемостью_id, таким образом у вас будет две оценки одним и тем же клиентом за один сеанс,

zjbarg 24.10.2018 19:20

Другие вопросы по теме