【问题标题】:Polymorphic Relationship with Multiple Associations多关联的多态关系
【发布时间】:2015-06-22 00:04:39
【问题描述】:

我正在尝试使用中间表来表示两个不同用户表(员工和非员工)之间的赞助关系,并满足以下要求:

  • 赞助商可以是员工或非员工。
  • 员工/非员工只能属于一个赞助商。
  • 一个员工可以有很多赞助商。

我注意到 Laravel 的多态关系只支持单一关联。通常,他们使用关系中的中间表来防止必须创建具有相同签名的多个表。就我而言,我需要对关系的双方进行多态化,因为在任何时候我都可以让赞助商/赞助人属于任一表。我不确定我是否正确,目前有点难过。

这是我目前拥有的:

Employees
id
sponsor_id

NonEmployees
id
sponsor_id

Sponsors
id
sponsorable_id
sponsorable_type

接下来,我设置以下模型:

模型/Employee.php

public function sponsors() {
    return $this->morphMany('Sponsor', 'sponsorable');
}

模型/NonEmployee.php

public function sponsors() {
    return $this->morphMany('Sponsor', 'sponsorable');
}

Models/Sponsor.php

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

通过此设置,我能够对 Sponsors 表执行一般查找查询,然后对其进行逆向工程以检索赞助商的名称。

Sponsor::with('sponsorable')->get();
Sponsor::find(1)->sponsorable;

【问题讨论】:

  • 你描述的“赞助商”和“员工”之间的关系看起来像一个“树”结构。那是对的吗?即一名员工既可以是“赞助人”,也可以是另一名员工的“赞助人”?
  • 是的,没错。 “非员工”也是如此。对于这个特定的问题,它们之间几乎没有区别,只是它们位于具有不同架构的不同表中。有什么想法吗?
  • 您是否有适当的逻辑来执行您的规则?我正在考虑“关系”中的“周期”。更像是“有向图”。如果发生“循环”,处理过程中会发生什么?
  • 赞助功能是我正在开发的一项新功能,因此除了要求由客户设置之外,如果有更好的方法来解决这个问题,它并不是一成不变的。我不确定我是否遵循您对循环图和有向图的思路。你能详细说明一下吗?
  • 例如雇员 A 赞助雇员 B,雇员 B 赞助雇员 C,雇员 C 赞助雇员 A 等等。这里只是猜测。这可能不是问题。

标签: php laravel laravel-4 polymorphic-associations


【解决方案1】:

我想出了以下想法,利用现有的多态关系来处理多个关联。

首先,我将架构更改为:

Employees
id

NonEmployees
id

Sponsors
id
sponsored_id
sponsored_type
sponsorable_id
sponsorable_type

因此,我从每个帐户类型表中删除了赞助商 ID 字段,并向赞助商表添加了第二个多态关系。

我更新了模型如下:

Models/Employee.php & Models/NonEmployee.php

public function sponsorable()
{
    return $this->morphOne('Sponsor', 'sponsorable');
}

public function sponsors()
{
    return $this->morphMany('Sponsor', 'sponsor');
}

Models/Sponsor.php

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

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

现在,因为 Laravel 不支持 morphManyThrough() 关系类型,你会注意到我更改了一些函数的名称,以便在使用关系时它看起来更清晰,因为我必须从一个开始表通过中间表,然后到第三个表以获取我想要的信息。

有了这个结构,我可以做到以下几点:

$employee = Employee::find(2)->sponsorable->sponsor; // Gets employee's sponsored party
$sponsors = $employee->sponsors; // Gets individual that the employee is sponsoring.
foreach ($sponsors as $sponsor)
    echo $sponsor->sponsorable->first_name;
$employee->sponsors()->save(new Sponsor()); // New sponsor
$non_employee->sponsors()->save(new Sponsor()); // New sponsor

我还可以执行反向查找:

Sponsor::find(1)->sponsor->first_name; // Sponsoring party
Sponsor::find(1)->sponsorable->first_name; // Party being sponsored

【讨论】:

  • 上面的代码仍然用于我需要它的应用程序。老实说,最棘手的部分是赞助商的语法,因为赞助方是“赞助商”,而被赞助方也是“赞助商”。这更像是一个命名约定障碍,而不是代码障碍。
猜你喜欢
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-25
相关资源
最近更新 更多