简化数据库关系设计

时间:2019-03-21 09:59:57

标签: php mysql laravel

我有一个Laravel小项目,成员可以付费参加课程,支付保险,活动费用或通过特殊类型的考试。

因此我有5个表membersclassesinsuranceeventsexams,我需要添加payments表这样我就可以跟踪每个表格的会员付款。

因此,目前payments表将如下所示:

id      date            amount      member_id   class_id    insurance_id    event_id    exam_id
1       2019-01-01      150         2           1           NULL            NULL        NULL
2       2019-01-01      250         11          NULL        14              NULL        NULL
3       2019-01-01      220         15          NULL        NULL            6           NULL
4       2019-01-01      350         32          NULL        NULL            NULL        8

有没有一种更好的方法,而无需: 付款表中的class_id, insurance_id, event_id, exam_id字段,因为我想这会使关系变得更加复杂,也许还可以简单地使用Laravel作为PHP框架进行数据库查询。

2 个答案:

答案 0 :(得分:1)

在一个表中不使用所有ID的情况下,使用事务表,而在所有这些表中使用该transaction_id。

表交易=> ID,付款数据,created_at,created_by等

表事件=> ID,名称,transaction_id等

答案 1 :(得分:1)

我认为最好的方法是一对多的多态关系。

数据库/迁移设置

要这样做,您需要:

  • 用于保存成员数据的members表。
  • 系统中每种类型的应付实体classesinsuranceeventsexams)的一个表
  • 一个payments表,其结构如下:
Schema::create('payments', function (Blueprint $table) {
    $table->increments('id');

    // Payment related fields like date and amount

    $table->unsignedInteger('member_id');
    // Assuming id is the primary key on the members table
    $table->foreign('member_id')->references('id')->on('members');

    // This one will create two fields:
    //  - payable_type
    //  - payable_id
    $table->morphs('payable');
});

这样,每条记录将包含进行付款(通过member_id)和付费实体(通过payable_typepayable_id)的成员。

雄辩的模型关系

然后,您必须在付款模型上设置变体关系,例如:

// app\Payment.php

class Payment extends Model
{
    // ...
    public function payable()
    {
        return $this->morphTo();
    }

    public function member()
    {
        return $this->belongsTo(Member::class);
    }
}

您的会员模型为:

// app\Member.php

class Member extends Model
{
    // ...    
    public function payments()
    {
        return $this->hasMany(Payment::class);
    }
}

对于每个应付款实体:

// app\Insurance.php

class Insurance extends Model
{
    // ...

    public function payments()
    {
        return $this->morphMany(Payment::class, 'payable');
    }
}
// app\Event.php

class Event extends Model
{
    // ...

    public function payments()
    {
        return $this->morphMany(Payment::class, 'payable');
    }
}
// app\Exam.php

class Exam extends Model
{
    // ...

    public function payments()
    {
        return $this->morphMany(Payment::class, 'payable');
    }
}
// app\Course.php

// I renamed "Class" payable entity to "Course"
// as "class" is a reserved keyword in PHP and
// you can't give a class the name "Class".
class Course extends Model
{
    // ...

    public function payments()
    {
        return $this->morphMany(Payment::class, 'payable');
    }
}

用法

如果您需要检索用户进行的所有付款(不同类型),则只需查询成员模型,如下所示:

$member = Member::with('payments.payable')->first();
dd($member->payments);

如果您相应地设置模型关系,Laravel将基于具有匹配member_id的每个记录的payable_type和payable_id解析不同的正确Eloquent模型实例。

因此,$member->payments将是付款实例的集合,每个实例都与InsuranceExamCourseEvent中的一个相关类(基于存储在数据库中的payable_type)。

作为参考和更详细的用法,您可以查看Laravel的官方文档here