多关联的多态关系

时间:2015-04-15 20:26:29

标签: php laravel laravel-4 polymorphic-associations

我试图使用中间表来表示两个不同用户表(员工和非员工)之间的赞助关系,具有以下要求:

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

我注意到Laravel的Polymorphic Relationships仅支持单个关联。通常,它们使用关系中的中间表来防止必须创建具有相同签名的多个表。在我的情况下,我需要改变关系的两个方面,因为在任何时候我都可以让赞助商/赞助人属于任何一个表。我不确定我是否正确行事,此刻还有点难过。

这是我目前所拥有的:

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');
}

模型/ Sponsor.php

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

通过此设置,我能够对Sponsors表执行常规查询查询,然后对它们进行反向工程以检索赞助商的名称。

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

1 个答案:

答案 0 :(得分:3)

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

首先,我将架构更改为:

Employees
id

NonEmployees
id

Sponsors
id
sponsored_id
sponsored_type
sponsorable_id
sponsorable_type

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

我更新了模型如下:

Models / Employee.php&模型/ NonEmployee.php

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

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

模型/ Sponsor.php

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

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

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

通过这种结构,我可以做到以下几点:

$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