数据库建模:按实体类型的空外键

Posted

技术标签:

【中文标题】数据库建模:按实体类型的空外键【英文标题】:database modeling: null foreign keys by entity type 【发布时间】:2021-02-05 06:56:20 【问题描述】:

我需要一些帮助来设计我的数据库关系。 我有这些表:文档、公司、个人和用户。文档可以是内部的或外部的。

如果是外部的,可以由公司或个人签名。 如果是内部的,则必须由用户签名。

在任何情况下,文档都是由单个实体(公司、个人或用户)签署的。我正在考虑通过以下方式创建文档表:

documents
----------
id_document
...
type
id_user
id_company
id_indiv

其中type可以是0:内部,1:外部,id_userid_companyid_indiv是各个表的外键,可以为空。这个逻辑可以吗?有人可以建议我一个更好的主意吗?

【问题讨论】:

【参考方案1】:

Laravel 的 Eloquent ORM 提供了 Polymorphic 关系来处理这类问题。

更具体地说,您可以放置​​两个字段; documentable_typedocumentable_id 在您的 document 表中。然后将这些关系方法添加到每个模型中;

class Document extends Model

    /**
     * Get the owning imageable model.
     */
    public function signer()
    
        return $this->morphTo();
    


class User extends Model

    /**
     * Get the documents signed by this user.
     */
    public function documents()
    
        return $this->morphMany('App\Models\Document', 'documentable');
    


class Company extends Model

    /**
     * Get the documents signed by this company.
     */
    public function documents()
    
        return $this->morphMany('App\Models\Document', 'documentable');
    


class Individual extends Model

    /**
     * Get the documents signed by this individual.
     */
    public function documents()
    
        return $this->morphMany('App\Models\Document', 'documentable');
    

那么就可以使用下面的sn-ps;

$document->signer; // This returns either user or company or individual
$company->documents; // This returns a collection of document models which is signed by this company
$individual->documents;
$user->documents;

更多详情,请查看此链接; https://laravel.com/docs/8.x/eloquent-relationships#polymorphic-relationships

【讨论】:

我真的很喜欢你的回答。但我有一个疑问。公司,个人用户是旧表,我无法修改。例如,individal 有两列:first_name,last name,company 有:bussines_name,user 有一个名为:names 的列。如何获取包含歌手姓名的文件列表。 class Individual: public function name() return $this->first_name . ' ' . $this->last_name; class Company: public function name() return $this->bussines_name; 所以我可以做 $document->signer->name();对吗? $document->signer 的类型因上下文而异。正如我在回答中提到的,它既不能是 User 模型,也不能是 Company 模型或 Individual 模型。因此,最好为每个模型添加名为 name() 的常用方法。 或者也定义自定义访问器(例如getNameAttribute)。

以上是关于数据库建模:按实体类型的空外键的主要内容,如果未能解决你的问题,请参考以下文章

如何定义一个维度,以便在显示所有值时不忽略 FK 中的空值?

在 cassandra 中使用可能的空值对嵌套数据进行建模

sql数据建模器中的外键问题

实体框架代码优先空外键

无法插入具有空外键的实体

《Entity Framework 6 Recipes》翻译系列 -----第二章 实体数据建模基础之有载荷和无载荷的多对多关系建模 (转)