首页 > 解决方案 > Laravel 与自定义数据透视表的多态关系

问题描述

我有以下

    Schema::create('bursary_providers', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('bursary_provider',64);
        $table->timestamps();
    });

    Schema::create('bursary_provider_contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->integer('bursary_provider_id')->unsigned()->index();
        $table->foreign('bursary_provider_id')->references('id')->on('bursary_providers')->onDelete('cascade');
        $table->integer('contact_id')->unsigned()->index();
        $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
        $table->timestamps();
    });

    Schema::create('contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('contact_name', 32);
        $table->timestamps();
    });

1)是的,我知道这不遵循存储“类型”的典型约定。我这样做是为了参照完整性。

2)我将它存储在一个自定义的命名数据透视表中,因为它对我来说更有意义。Laravel 数据透视表的要求是它的字母顺序,但让我们保持这样,因为我希望命名为 parent_child

现在,如何设置我的模型?据我了解,这种情况将是一个 morphMany (除了“bursary_providers”之外还有其他父母——为了避免混淆而省略了)。所以我会在我的 BursaryProvider 模型中使用以下内容:

public function contacts() {
    return $this->morphMany('App\Contact');
}

我的联系人模型中的以下内容:

public function bursary_provider () {
    return $this->morphTo();
}

如何更改上述内容,以便它们使用bursary_providers.id / contacts.id和数据透视表bursary_provider_contacts(使用bursary_provider_idcontact_id)正确连接?

// 编辑为清楚起见,除了 bursary_providers 之外的另一个“父级”(bursary_providers 可以有很多联系人;bursary_administrators 可以有很多联系人;联系人属于一个):

    Schema::create('bursary_administrators', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->string('bursary_administrator',64);
        $table->timestamps();
    });

    Schema::create('bursary_provider_contacts', function (Blueprint $table) {
        $table->increments('id')->unsigned()->index();
        $table->integer('bursary_administrator_id')->unsigned()->index();
        $table->foreign('bursary_administrator_id')->references('id')->on('bursary_administrators')->onDelete('cascade');
        $table->integer('contact_id')->unsigned()->index();
        $table->foreign('contact_id')->references('id')->on('contacts')->onDelete('cascade');
        $table->timestamps();
    });

标签: laravelrelationshiplaravel-5.6

解决方案


如果您不想遵循 Laravel 命名约定,我认为我强烈建议您不要这样做。主要是因为如果您遵循约定,它会起作用,其次,您只是为自己做更多的工作!

因此,您需要做的是将所需的表名作为关系的第二个参数传递。我不明白你为什么使用morphMany,你应该使用belongsToMany

例子

public function contacts() {
    return $this->belongsToMany(App::Contact, 'bursary_provider_contacts');
}

public function bursary_provider () {
    return $this->belongsToMany(Bursary provider::class, 'bursary_provider_contacts');
}

编辑

就像关于关系类型的脚注

假设您有一个产品模型、一个订单模型和一个发票模型。

现在产品可以属于订单,也可以属于发票。

这并不能证明多态关系是合理的,这意味着您将拥有以下表格:

产品订单发票 order_product invoice_product

现在是一个多态的例子,Laravel 使用这个相同的例子,因为它很常见。

假设你有一个帖子模型、一个视频模型和一个评论模型。

现在帖子模型可以有评论

视频模型可以有评论。

因此,无需构建 PostComment 和 VideoComment 模型,您可以简单地构建 Comment 模型,并通过定义多态关系,两个模型的评论将与所需模型相关联地存储。

我不想居高临下,但要认真查看 Laravel 文档,它们非常有帮助。

https://laravel.com/docs/5.6/eloquent-relationships#polymorphic-relations

推荐阅读