Laravel多对多关系的实现方式

6

我正在使用多对多的关系,我想为这个属性设置两个值。

产品,

属性,

属性产品 => 产品ID、属性ID、值

enter image description here

我知道这不正确,但我想向您展示我的意图。

$product->attributes()->sync([
            1 => [
                'value' => 'sky'
            ],
            1 => [
                'value' => 'night'
            ],
        ]);

更新2

Schema::create('attribute_product', function (Blueprint $table) {

$table->unsignedInteger('product_id');
$table->unsignedInteger('attribute_id');
$table->text('value')->nullable();
$table->integer('devalue_id')->nullable(); // value id 

$table->primary(['product_id', 'attribute_id', 'devalue_id']);

});

更新1

我需要设置天空和夜晚。

product_id  attribute_id      value       devalue_id
1           1                 sky         1
1           1                 night       2
...

1
你可以重新表达一下吗? - ka_lin
@ImAtWar https://www.digikala.com/Product/DKP-149283 这台笔记本电脑具有多个属性值: - danial dezfooli
用法:多媒体,窄小轻便。它如何保存这些值? - danial dezfooli
你正在使用哪个版本的Laravel? - Rwd
@RossWilson 我已经打了5.4的标签。 - danial dezfooli
2个回答

3
对于这种情况,我可以看到两个选项: 1. 手动添加和移除你想要的记录。然而,这可能会导致在检索数据时返回多个相同的属性值,但是你可以将集合上使用groupBy来解决这个问题(如果这对你来说是一个问题的话)。 2. 你可以在枢轴表的值列中存储一个JSON对象。这样可以允许你为同一属性拥有多个值。为此,你可以创建一个AttributeProductPivot类(或任何你想称之为的名称),该类扩展了Illuminate\Database\Eloquent\Relations\Pivot并在其中添加一个casts属性,例如:
class AttributeProductPivot extends \Illuminate\Database\Eloquent\Relations\Pivot
{
    /**
     * The attributes that should be casted to native types.
     *
     * @var array
     */
    protected $casts = [
        'value' => 'collection', //or object or array
    ];

}

然后将你的attributes()关系更改为:

public function attributes()
{
    return $this->belongsToMany(Attribute::class)
        ->using(AttributeProductPivot::class)
        ->withPivot('value');
}
using() 允许您设置一个不同于默认的 PIVOT 模型。如果需要反向关系,也不要忘记进行相同的操作。
在添加/同步时,您需要自己将 value 属性转换为 JSON。
希望这可以帮助您!

你的意思是将天空、田野夜晚保存为JSON格式吗? - danial dezfooli
@danialdezfooli 不,搜索并不那么容易。如果您使用的是mysql 5.7+,则可以将列值从文本更改为json,然后您就可以查询它,但速度会慢得多。我只是提供了一个潜在的替代方案,但如果您需要搜索,这可能不是最佳选择。从您的表结构来看,您正在尝试创建类似于EAV的东西。我建议您查看像这样的东西 https://github.com/IsraelOrtuno/Eavquent/tree/3bd12b0b5cb0014099bb05c9af2a42705e403afe 和 https://lacke.mn/building-an-entity-attribute-value-system-part-i-understan - Rwd
如果您尝试使用eav路线,我建议使用多态关系将产品与其属性值链接起来。 - Rwd
我已经创建了\App\AttributeProductPivot.php,但是出现了Class '\App\AttributeProductPivot' not found的错误。 - danial dezfooli
它可以作为“json”工作,但是如果没有使用json,能帮我解决我的代码问题吗? - danial dezfooli
显示剩余4条评论

1

我不完全确定你想做什么,所以我会讨论两种不同的情况。

1:创建一个属性并将其链接到产品。在这种情况下,你有一个产品并知道一个属性的名称,但它还没有出现在你的属性表中。它看起来会像这样:

$product->attributes()->saveMany([
   new App\Attribute(['title' => 'sky']),
   new App\Attribute(['title' => 'night']),
]);

2:将现有属性附加到产品上。在这种情况下,您已经在属性表中拥有该属性并查找了它。实际上,它非常相似,只是要找到属性。

$attribute1 = Attributes::where('title', 'sky')->first();
$attribute2 = Attributes::where('title', 'night')->first();

$product->attributes()->saveMany([
    $attribute1,
    $attribute2,
]);

$product->attributes()->detach(); $product->attributes()->attach([...]) ; 我现在正在执行这个操作。 - danial dezfooli
1
不必先进行分离,实际上您可以直接使用 $product->sync([...]),它将清除数组中不存在的任何属性并添加存在的任何属性。代码会更加整洁。 :) - llhilton
啊,我以前从未使用过三个字段的主键。如果我需要在数据透视表上设置主键,通常我只会创建一个唯一的ID字段,因为我很懒:D - llhilton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接