【问题标题】:Laravel relations with composite, non-standard foreign keysLaravel 与复合、非标准外键的关系
【发布时间】:2016-11-12 21:38:27
【问题描述】:

不幸的是,我需要从第三方供应商导入数据,并在我的 laravel 项目中使用他们的非标准数据库架构。此外,我需要在我的数据库中存储多个“公司”,每个公司都有自己的一组用户。

我正在尝试找出使用 Eloquent 处理这些表之间关系的最佳方法(如果可以的话)。例如,我的表结构是这样的:

 BmPerson
  'id',
  'firmId',
  'personId'

BmCoverage
  'id',
  'firmId',
  'personId',
  'securityId'

BmSecurity
  'id',
  'firmId',
  'securityId'

...例如,我需要通过“BmCoverage”表将“BmPerson”与许多“BmSecurity”相关联。

但我需要以某种方式使用复合键,因为我在每个表中存储了多个“公司”(根据第 3 方供应商的数据库架构)。

到目前为止,我使用的一种方法是范围界定,例如:对于我的 BmCoverage 模型:

 public function scopeFromFirm($query,$firmId){
  return $query->where('firmId','=',$firmId);//->where('personId','=',$personId);}

public function scopeFromPerson($query,$personId){
  return $query->where('personId','=',$personId);//->where('personId','=',$personId);}

然后我可以检索个人的保险范围列表,但我仍然需要以某种方式将“BmCoverage”与“BmSecurities”相关联。我想我也可以在 BmSecurities 类中添加一个范围,但使用 Eloquent 会更好。

有没有人想出在 laravel 模型关系中使用复合键的好方法,还是我应该坚持使用作用域方法?

【问题讨论】:

  • 你的模型关系是什么样的?
  • 为什么你有 2 个 BmCoverage?。
  • 抱歉,我已经删除了第二个 - 是重复的。现在我无法关联这些模型,因为我需要跨 2 个键来关联(例如,在将 BmPerson 与 BmCoverage 关联的情况下,firmId 和 personId)。那有意义吗?我有一个唯一的 id 列,但我需要能够基于 2 个键而不是一个键进行关联。
  • 这是另一种表述方式:我使用的第三方供应商供应品,例如“firmId”和“securityId”。但是,securityIds 可以重复。所以firmId 1 可以有securityIds 1,2,3。 FirmId 2 也可以有 securityIds 1,2,3。现在我将证券存储在一个表中,firmIds 在一个单独的列中,这不适用于 laravel 的关系工具。有没有办法可以更改数据库结构以使其兼容,或者我应该将其保留为复合键并使用手动查询?谢谢。
  • 虽然 BmCoverage 是枢轴模型,您可以使用 laravel.com/docs/5.0/eloquent#working-with-pivot-tables,但我会使用查询范围概念 laravel.com/docs/5.2/eloquent#query-scopes

标签: laravel


【解决方案1】:

有一个包here 似乎非常适合您的情况:

Compoships 提供了基于两个指定关系的能力 Laravel 5 的 Eloquent 中的(或更多)列。需要匹配多个 经常出现 Eloquent 关系定义中的列 与第三方或预先存在的架构/数据库合作时。

你会这样使用它:

class BmPerson extends Model
{
    use \Awobaz\Compoships\Compoships;

    public function bmCoverages()
    {
        return $this->hasMany('App\BmCoverage', ['firmId', 'personId'], ['firmId', 'personId']);
    }
}

如果每个BmSecurity 恰好属于一个BmCoverage,并且每个BmCoverage 恰好属于一个BmPerson,那么在BmCoverage DB 中用bmperson_id 替换'firmId', 'personId' 可能更容易;和'firmId', 'securityId'bmcoverage_idBmSecurity。然后就可以一键使用默认的hasMany关系了。

【讨论】:

  • 使用compoship,如何实现hasManyThrough()?
  • @DelowarHossain 似乎不可能。但可以肯定的是,您可以询问存储库所有者
  • 嘿@Adam,如果您能帮我理解Compoships 的用法,那就太好了。文档中提供的示例对我来说似乎不清楚。
  • @JunaidQadir 只需将use \Awobaz\Compoships\Compoships; 放入您的班级。该 trait 将覆盖 hasMany 函数,因此您可以指定两个 id 列。
  • 对不起,大家,我创建了另一个帖子,我不得不发布@Adam 的链接以及任何可以帮助我的人stackoverflow.com/questions/61501540/…
【解决方案2】:

您需要的一切都可以在这里找到https://laravel.com/docs/5.2/eloquent-relationships

您可以轻松定义哪些列应该是被引用的键。

例子:

public function bmCoverages() {
    return $this->hasMany('App\BmCoverage', 'firmId', 'id');
}

这可能属于您的 App\Firm 或其他名称。

通常 hasMany 关系看起来像这样

return $this->hasMany('App\Comment', 'foreign_key', 'local_key');

如您所见,您可以指定键。

【讨论】:

  • 对,但问题是我需要能够跨 2 个键关联。因此,“BmPerson”需要与许多“BmCoverages”相关联,但我不能使用唯一密钥,因为第 3 方供应商在该公司内有一个“firmId”然后是“personId”。所以firmId 1可能有personIds 1,2,3;和firmId 2 也可能有personIds 1,2,3
  • 感谢您抽出宝贵的时间来回答,但我正试图找出我从中导入数据的第 3 方供应商没有为我需要的项目提供唯一密钥的情况参考,而不是如何在基础级别使用关系。当我尝试使用 larvae 的关系时,您认为我应该尝试为项目分配我自己的唯一键吗?
  • 供应商应该以某种方式提供唯一的数据标识符,不是吗?我需要更多关于您收到的信息以提供更详细的提示。我只能猜测:可能会从两个甚至三个字段一起创建主键以确保唯一性
  • 我实际上并不认为这是一个丑陋的解决方案。将两个字段组合为主键是很常见的事情
  • Having two fields combined as a primary key is a pretty common thing 如果您创建的另一列只是其他两列的组合,则它不是第三范式。问题是,每当更新一列时,都必须更新相关列,这使得维护变得困难。
【解决方案3】:

正如其他人所说,您需要使用HasManyHasManyThrough 关系。

从您的表定义中,您只需访问:

  • Person->BmCoverage(s)
  • Person->BmSecurity(s) 个人。

我认为这里的主要问题是将 BmSecurity 与 BmCoverage 链接起来,因为显然没有 coverage_id per BmSecurity,而是通过 firmIdsecurityId 的复合映射。

不幸的是,在这种情况下,Laravel 并没有正式支持复合键,虽然你可以使用 trait like this... 但你也可以通过一些棘手的 hasMany 来实现同样的效果。

即关于 BmCoverage

$this->hasMany('BmSecurity', 'securityId', 'securityId')
     ->andWhere('firmId', '=', $this->firmId);

同样适用于 BmPerson 的 BmSecurity,使用 HasManyThrough

希望对您有所帮助。

【讨论】:

  • 拜托,反向关系是属于怎样的?
  • 你好@somezombie 我不太明白你的问题。如果您对 Stackoverflow 有任何疑问,请给我发送链接,我会看看。谢谢
【解决方案4】:

阅读 laravel hasManyThrough 关系。它将帮助您更轻松地编写此查询

https://laravel.com/docs/5.1/eloquent-relationships#has-many-through

【讨论】:

  • has-many-through 关系不包括复合键。
  • 是否可以同时使用两个 laravel 关系。
猜你喜欢
  • 2020-08-13
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多