php - 使用 Laravel 5 热切加载多个索引关系

标签 php laravel eloquent

我目前正在开展一个项目,我必须使用一个已有 10 年历史的数据库,该数据库的构建很糟糕。 无论如何,我有两张表:一张用于产品,一张用于颜色。每件产品均由引用标识,每种颜色均由其自己的引用+其产品的引用标识。 例如,我有一款产品编号为 123。该产品有 3 种颜色:123-01、123-02 和 123-03。这两个值分为两列:nocol(产品引用)和 nopat(颜色引用)。 我无法为每种颜色提供唯一的 id,因为数据库每天晚上都会被删除,因此 id 总是在变化(我知道这很奇怪)。

现在我有三个模型:Product、Color 和 CartItem。我的颜色模型与产品模型具有一对一的关系。我的 CartItem 与我的 Color 模型具有一对一的关系,其定义如下:

public function color() {
  return $this->hasOne('App\Color', 'nocol', 'color_ref')->where('nopat', $this->product_ref);
}

这工作正常,因为我可以使用简单的 $cartItem->color 从 CartItem 检索颜色。问题是它不适用于急切加载。当我尝试使用以下内容检索我的 CartItems 时:

CartItem::with('product', 'color')->get();

当我转储结果时,我最终得到了一个空关系。

当索引是两个独立的列时,还有其他方法可以编写这种关系吗?


编辑 07-10

根据要求,这是一个非常简单的数据库 View 。正如我所说,我必须使用无法修改的旧数据库。解决我的问题的最简单方法是向我的颜色表添加一个唯一的 ID,但我无法做到这一点。

我的产品型号有一个唯一的 ID pat_nopat。一种产品可以有多种颜色。我的颜色模型有两列 col_nopatcol_nocolcol_nopat 列引用产品 ID。这两列一起构成了颜色模型的唯一 ID。

我的 OrderItem 模型通过 col_nopatcol_nocol 引用颜色,分别称为 product_refcolor_ref

enter image description here

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


编辑 07-11

我尝试使用 join 子句而不是 where 子句来更改关系。急切加载可以工作,但结果是错误的。

如果我有两个具有相同颜色引用但产品引用不同的购物车项目,则我得到的结果是错误的。 假设我有两个这样的 CartItem:

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

最佳答案

加入怎么样? (顺便问一下,这不是 belongsTo 关系而不是 hasOne 吗?)

public function color()
{
    return $this->belongsTo(Color::class, 'color_ref')
        ->join('order_items', 'colors.col_nopat', '=', 'order_items.product_ref');
}

编辑后,我发现此解决方案存在问题。在 Eloquent 中处理复合主键总是很困难,就像本例一样。

您可以作一点作弊,立即加载所有匹配的颜色,然后按 product_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();
}

(这样您可以避免经历产品关系。)

关于php - 使用 Laravel 5 热切加载多个索引关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44703951/

相关文章:

php - 在 PHP 中使用数组类类型参数

php - 无法在 PHPStorm 10.0.1 中为 artisan 制作命令行工具

php - 如何在 Laravel 中按字母顺序对记录进行排序

php - NodeJS 推送队列,由 Laravel worker 使用

laravel - 在 Laravel Eloquent 中,如何检查一个 "has"中是否存在多个关系?

php - 在组件中使用模型

php - WordPress 数据库查询不返回结果

laravel - Ajax中间件

php - Laravel:未找到 Eloquent/Tinker 类

php - Eloquent - 调用未定义的关系