如何使用雄辩的ORM

时间:2018-10-22 22:57:39

标签: php mysql laravel eloquent laravel-5.7

对于Laravel来说是新手,但我爱我到目前为止所看到的。

我正在开发一个客户可以参加会议的应用程序,并且许多客户可以参加会议。除此之外,客户还可以在各自参加的会议中完成评估(即一位客户=一项评估)。还值得指出的是,他们可能会也可能不会完成评估。

最好的解释方式是...

enter image description here

同样重要的是要指出数据必须一致-必须在有客户出席的会议中进行完整的评估。即客户必须出席会议-反之亦然-客户无法完成并评估他或她不出席的会议。

这更多的是尝试将我的头缠在最佳结构上,并使用Laravel中的Eloquent ORM。我知道我可以为这个问题提供一个可行的解决方案,但是肯定会出现乱码,但我宁愿知道正确的方法。

一些相关代码:

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. 创建一个单独的表“ Attendance”和一个关联的“ pivot类”,即扩展“ Pivot not Model”-对此一无所知!

我设法使用简单的表来结构化数据,并在Laravel之外使用INNER JOIN,但想了解如何最好地用Eloquent来实现。

我还使用Pivot(即,扩展了Pivot而不是Model)或hasManyThrough()关系看到了EmiratesToMany()关系。

我还看到了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();
    }
}

我故意重命名了数据透视表,以反映数据透视表类。

我已经将一些虚拟数据放入出勤表,使得:

enter image description here

当我在客户端会话中查询客户端ID 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。我认为不需要评估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}}]

所以我想我很接近。

1 个答案:

答案 0 :(得分:0)

因此,如果您有client_sessionattendanceid的{​​{1}}或client_id表,并且将此表用作评估表中的外键。

事情是数据透视表可以是模型

请参见Many to Many:定义自定义中间表模型

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:是指客户端和会话