Php 渴望加载与Laravel 5的多索引关系

Php 渴望加载与Laravel 5的多索引关系,php,laravel,eloquent,Php,Laravel,Eloquent,我目前正在做一个项目,我必须使用一个10年的数据库,它的结构很糟糕。 总之,我有两张桌子:一张是产品,一张是颜色。每种产品都有一个参考号,每种颜色都有自己的参考号+产品的参考号。 例如,我有一个产品的参考123。本产品有三种颜色:123-01、123-02和123-03。这两个值分为两列:nocol(产品参考)和nopat(颜色参考)。 我不能为每种颜色都有一个唯一的id,因为数据库每晚都会被删除,所以id总是在变化(我知道这很奇怪) 目前我有三种型号:产品、颜色和商品。我的颜色模型与产品模型有

我目前正在做一个项目,我必须使用一个10年的数据库,它的结构很糟糕。 总之,我有两张桌子:一张是产品,一张是颜色。每种产品都有一个参考号,每种颜色都有自己的参考号+产品的参考号。 例如,我有一个产品的参考123。本产品有三种颜色:123-01、123-02和123-03。这两个值分为两列:nocol(产品参考)和nopat(颜色参考)。 我不能为每种颜色都有一个唯一的id,因为数据库每晚都会被删除,所以id总是在变化(我知道这很奇怪)

目前我有三种型号:产品、颜色和商品。我的颜色模型与产品模型有一对一的关系。我的CartItem与我的颜色模型有一对一的关系,定义如下:

public function color() {
  return $this->hasOne('App\Color', 'nocol', 'color_ref')->where('nopat', $this->product_ref);
}
CartItem::with('product', 'color')->get();
product_ref | color_ref
----------- | ---------
1234        | 01
5678        | 01
这很好,因为我可以用一个简单的
$CartItem->Color
从CartItem检索颜色。问题是,它不适用于即时加载。当我尝试使用以下内容检索CartItems时:

public function color() {
  return $this->hasOne('App\Color', 'nocol', 'color_ref')->where('nopat', $this->product_ref);
}
CartItem::with('product', 'color')->get();
product_ref | color_ref
----------- | ---------
1234        | 01
5678        | 01
当我转储结果时,结果是空关系

当索引是两个独立的列时,有没有其他方法来编写这种关系


编辑07-10

根据要求,这里是数据库的一个非常简单的视图。正如我所说,我必须使用一个旧的数据库,我不能修改它。解决我的问题最简单的方法是在我的颜色表中添加一个唯一的ID,但我不能这样做

我的产品型号有一个唯一的id
pat\u nopat
。一种产品可以有多种颜色。我的颜色模型有两列
col\u nopat
col\u nocol
col\u nopat
列引用产品ID。这两列一起是颜色模型的唯一ID

我的订单项模型通过
col\u nopat
col\u nocol
引用一种颜色,这两种颜色被称为
product\u ref
Color\u ref

当我显示特定客户的订单历史记录时,我还通过OrderItem模型显示一些有关颜色的信息。问题是它执行了太多的查询,因为我找不到一种方法来加载OrderItem和颜色之间的关系


编辑07-11

我尝试使用join子句而不是where子句来更改关系。快速加载有效,但结果是错误的

如果我有两个相同颜色参考但不同产品参考的CartItem,我得到的结果是错误的。 假设我有两个这样的项目:

public function color() {
  return $this->hasOne('App\Color', 'nocol', 'color_ref')->where('nopat', $this->product_ref);
}
CartItem::with('product', 'color')->get();
product_ref | color_ref
----------- | ---------
1234        | 01
5678        | 01
我用where关系得到了正确的结果,但我不能立即加载

但是,联接关系为两行返回1234-01,因为它为每个颜色引用获取第一个结果。 如果查看调试栏中的查询,我会得到以下结果:

select * from `colors` inner join `cart_items` on `colors`.`col_nopat` = `cart_items`.`product_ref` where `colors`.`col_nocol` in ('01')
select * from `products` where `products`.`pat_nopat` in ('1234', '5678')

将关系定义为:

public function color()
{
    return $this->hasOne('App\Color', 'nocol', 'color_ref');
}
然后使用:

加入怎么样?(顺便问一下,这不是一种
属于
关系,而不是
有一种
?)


编辑后,我发现这个解决方案存在问题。在这种情况下,用雄辩的语言处理复合主键总是很困难的

你可以作弊一点,然后加载所有匹配的颜色,然后按
product\u ref
过滤。这样可以避免触发每个CartItem模型的单独查询。考虑这一点:

// Product.php
public function colors()
{
    return $this->hasMany(Color::class, 'col_nopat', 'pat_nopat');
}

// ----

// CartItem.php
public function product()
{
    return $this->belongsTo(Product::class, 'product_ref');
}

public function getColorAttribute()
{
    return $this->product->colors
        ->where('col_nopat', $this->product_ref)
        ->first();
}
然后加载与
CartItem::with('product.colors')
的关系,然后可以执行
$item->color


备选方案:

// CartItem.php
public function color()
{
    return $this->hasMany(Color::class, 'col_nocol', 'color_ref')
        ->select('colors.*')
        ->join('items', function ($join) {
            $join->on('colors.col_nocol', '=', 'items.color_ref');
            $join->on('colors.col_nopat', '=', 'items.product_ref');
        });
}

public function getColorAttribute()
{
    return $this->getRelation('color')
        ->where('col_nopat', $this->product_ref)
        ->first();
}

(在这种情况下,您可以避免使用
产品
关系。)

产品参考
位于
CartItem
表中,因此这不会按您的想法工作。没错,我不能这样做,因为当我想要检索所有CartItems时,我没有productRef。你可以提供一个简单的ERD,在列上添加注释吗?当然,我更新了问题。知道这一点,为了使用复合PK,您可能需要使用。我会提供问题中的所有模型,包括它们之间的关系,并对其进行测试,以获得赏金:)@ThomasMoors我会的,但很明显OP已经具备了这一功能。只有这种
color
relationship错过了你这么多,这真的很有效:)看起来我得等24小时才能获得赏金,但我肯定会的@托马斯莫尔斯也感谢你;)当然没问题!谢谢你更新你的答案。您的第一个解决方案似乎运行良好!这一次我只需要三次检查:)我只需要在
getColorAttribute
函数中通过
col\u nocol
color\u ref
更改
col\u nopat
product\u ref
。然而,第二个不起作用。我得到一个错误,说这种关系不存在。如果有什么东西坏了,我会让你知道,否则我不会原谅你给你赏金;)