如何使用多个外键查询数据透视表Laravel 5 Eloquent

大卫·爱立信

我具有以下表结构:

| products | product_options | product_option_values | product_option_to_product |
+----------+-----------------+-----------------------+---------------------------+
| id       | id              | id                    | id                        |
|          |                 |                       | product_id                |
|          |                 |                       | product_option_id         |
|          |                 |                       | product_option_value_id   |

我的关系如下所示:

// Product.php
public function options()
{
    return $this->belongsToMany('App\ProductOption', 'product_option_to_product', 'product_id', 'product_option_id')->withPivot('product_option_value_id', 'product_id');
}

// ProductOption.php
public function values()
{
    return $this->belongsToMany('App\ProductOptionValue', 'product_option_to_product', 'product_option_id', 'product_option_value_id')->withPivot('product_id');
}

现在,当我尝试这个:

$products = Product::with('options')->with('options.values')->first();

要么

$products = Product::with('options.values')->first();

我获得所有可能的选项值,因为它不使用产品ID来加载选项值。

有谁知道我如何确保它仅加载属于该产品的值?

我可以直接在产品上与选项值建立联系,但是我确实需要将它们附加到它们所属的选项上。

编辑:

我用这样的联接尝试了它:

$products = Product::with(['options.values' => function($q) {
    $q->join('products', 'products.id', '=', 'product_option_to_product.product_id');
}])->first();

但这给出了相同的结果。

我目前已经实施了一个非常讨厌的修复程序,在我看来,我进行了一些检查:

@if($value->pivot->product_id == $product->id)
    <div class="checkbox">
        <label>
            <input type="checkbox" name="{{ $option->id }}" value="{{ $value->id }}"> {{ $value->language->name }}
        </label>
    </div>
@endif

但是,这对我来说不合适。

古斯塔沃·斯特劳布(Gustavo Straube)

您的问题在于表中的记录product_options不知道您要检索的产品。

基于您在问题中提到的数据库结构,我编写了以下几行:

$product = App\Product::with('options')->with('options.values')->first();
foreach ($product->options as $option) {
    foreach ($option->values as $value) {
        printf(
            "Product: %s, Option: %d, Value: %d\n",
            $product->id,
            $option->id,
            $value->id
        );
    }
}

上面的代码仅打印特定产品的选项和值的可能组合。我使用的是您在应用程序中创建的相同关系。

当我加载该代码时,Eloquent(Laravel的ORM)在数据库中运行以下查询:

-- Retrieves the first product
select * from `products` limit 1;

-- Retrieves all options using the product_id as condition
select `product_options`.*, `product_option_to_product`.`product_id` as `pivot_product_id`, `product_option_to_product`.`product_option_id` as `pivot_product_option_id`, `product_option_to_product`.`product_option_value_id` as `pivot_product_option_value_id` 
from `product_options` inner join `product_option_to_product` on `product_options`.`id` = `product_option_to_product`.`product_option_id` 
where `product_option_to_product`.`product_id` in ('1')

-- Retrieves all values using the option_id as condition
select `product_option_values`.*, `product_option_to_product`.`product_option_id` as `pivot_product_option_id`, `product_option_to_product`.`product_option_value_id` as `pivot_product_option_value_id`, `product_option_to_product`.`product_id` as `pivot_product_id` 
from `product_option_values` inner join `product_option_to_product` on `product_option_values`.`id` = `product_option_to_product`.`product_option_value_id` 
where `product_option_to_product`.`product_option_id` in ('1', '2')

如您所见,最后一个查询不使用product_id条件作为检索值的条件,因为product_optionstable不保存对productstable的引用

最后,我取得了与您相同的结果。尽管我正在搜索产品,但所有值都与一个选项相关。

最简单的解决方法是在调用关系时添加查询约束。像这样:

$product = App\Product::with('options')->with('options.values')->first();
foreach ($product->options as $option) {
    foreach ($option->values()->where('product_id', $product->id)->get() as $value) {
        printf("PRO: %s, OPT: %d, VAL: %d<br>\n", $product->id, $option->id, $value->id);
    }
}

请注意$option->values,我没有使用属性作为调用,而是使用了$option->values()作为方法。调用关系方法时,可以像使用查询构建器一样使用它。

如果您不想使用此解决方法,则可能需要更改数据库结构和模型类。

-

编辑

一种替代解决方案是使用查询生成器来获取特定产品的所有值。

您可以在控制器中执行以下操作:

$values = ProductOptionValue::select([
    'product_option_values.*',
    'product_option_to_product.option_id',
])
    ->join('product_option_to_product', 'product_option_to_product.product_option_value_id', '=', 'product_option_values.id')
    ->where('product_id', $product->id)
    ->get();

这样,您将获得特定产品的所有值(由其提供$product->id)及其相应的option_id

要在模板中使用上面查询的结果,您只需在复选框名称中做一个小改动:

<div class="checkbox">
    <label>
        <input type="checkbox" name="{{ $value->option_id }}" value="{{ $value->id }}"> {{ $value->language->name }}
    </label>
</div>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Laravel Eloquent的数据透视表,其中有一个表的2个外键和另一个表的1个外键

如何在Laravel 5中使用Eloquent更新数据透视表

与Eloquent Laravel 5的交易

Laravel Eloquent-使用数据透视表的ID作为另一个表中的外键

Laravel 5:如何使用Eloquent在数据透视表上进行联接查询?

Laravel 5:Eloquent的查询集合的“ orWhere”方法的替代方法

Laravel 5-如何通过查询生成器或Eloquent在两个以上的表/查询中使用联合?

Laravel Eloquent:用于关系的多个外键

Laravel / Eloquent:数据透视表上的条件

在Laravel 5中使用ORM Eloquent访问DBF表

Laravel Eloquent-查询数据透视表

如何使用Eloquent在数据透视表中插入多行?

如何使用Laravel Eloquent从多个表中获取数据

在Eloquent中将数据透视表与多个表连接

我如何使用Eloquent&Laravel 5查询多态数据透视表

Laravel 5模型:在Eloquent中不要包含某些列

laravel 5如何创建数据透视表

如何在 Laravel 5 中编写动态数量的 Eloquent 查询?

如何通过外键使用 Eloquent 搜索查询

Laravel 5 - 覆盖从 Eloquent 获取或选择

laravel5 Eloquent 和查询构建器

Foreach 插入 Laravel 5 Eloquent

Laravel Eloquent - 数据透视表

Laravel 5 Eloquent where with multiple or in Clauses

如何构建 Eloquent 查询来检索主表的记录,在 Laravel 5 PHP 中对其相关表应用 where 子句?

Laravel 5 Eloquent AND 而不是 where

Laravel Eloquent 如何为数据透视表选择使用条件“where”

laravel eloquent hasOneThrough 外键

如何在 Laravel eloquent 中查询数据透视表的计数