我的多对多关系只为每个项目保存一次数据,我找不到在将多个属性附加到多个项目时可能犯的错误。
这是我的模型:
项目
<?php
...
class Item extends Model
{
protected $fillable = [
'external_id',
'url',
'created_at',
'updated_at'
];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function attributes()
{
return $this->belongsToMany(AttributeValue::class);
}
}
属性
<?php
...
class Attribute extends Model
{
protected $fillable = [
'name'
];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function values()
{
return $this->belongsToMany(AttributeValue::class);
}
}
属性值
<?php
...
class AttributeValue extends Model
{
protected $fillable = [
'attribute_id',
'name',
];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function items()
{
return $this->belongsToMany(Item::class);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function attribute()
{
return $this->belongsTo(Attribute::class);
}
}
如您所见,我尝试将属性及其值分开,以便更好地访问每个值,例如 $item->attributes()
或 $attribute->values()
.
我的迁移如下所示:
项目
<?php
...
class CreateItemsTable extends Migration
{
public function up()
{
Schema::create('items', function ( Blueprint $table ) {
$table->increments('id');
$table->string('external_id');
$table->string('url');
$table->timestamps();
}
}
属性
<?php
...
class CreateAttributesTable extends Migration
{
public function up()
{
Schema::create('attributes', function ( Blueprint $table ) {
$table->increments('id');
$table->string('name');
$table->timestamps();
}
}
属性值
<?php
...
class CreateAttributeValuesTable extends Migration
{
public function up()
{
Schema::create('attribute_values', function ( Blueprint $table ) {
$table->increments('id');
$table->text('name');
$table->integer('attribute_id')->unsigned();
$table->foreign('attribute_id')->references('id')->on('attributes')->onDelete('cascade');
$table->timestamps();
}
}
...最后但并非最不重要的一点是,使用 Jeffrey Way 的酷 Laravel Extended Generators 创建的数据透视表
属性值项枢轴
<?php
...
class CreateAttributeValueItemPivotTable extends Migration
{
public function up()
{
Schema::create('attribute_value_item', function ( Blueprint $table ) {
$table->integer('attribute_value_id')->unsigned()->index();
$table->foreign('attribute_value_id')->references('id')->on('attribute_values')->onDelete('cascade');
$table->integer('item_id')->unsigned()->index();
$table->foreign('item_id')->references('id')->on('items')->onDelete('cascade');
$table->primary([ 'attribute_value_id', 'item_id' ]);
});
}
}
我知道,这是很多代码,但我认为这是帮助我解决这个问题所必需的。
想象一下,我正在获取具有品牌、尺寸、高度等属性的不同元素的对象。
当我尝试将它们附加到我的数据透视表时
$items = $this->getExternalItemsObject();
...
foreach($items as $item) {
$attributes = $item->Attributes->AttributesValueList;
foreach ( $attributes as $attribute )
{
$itemAttribute = Attribute::firstOrCreate([ 'name' => $attribute->Name ]);
$itemAttributeValue = AttributeValue::firstOrCreate(
[ 'name' => $attribute->Value[0] ],
[ 'attribute_id' => $itemAttribute->id ]
);
$itemAttributeValue->items()->attach($item->id);
}
现在,当循环第一个项目时,一切正常。所有属性 ID 均与相关项目 ID 一起存储在数据透视表中。但对于第二个、第三个、第 n 个项目,有时具有相同的属性,例如品牌(比如说耐克或类似的东西),关系将被跳过并且不会被保存。
这真的很奇怪,说实话让我有点发疯。
最佳答案
好吧,看来我没有遵循命名数据透视表的正确约定。
因此添加第二个参数 belongsToMany()
方法解决了。
这就是它的样子:
...
return $this->belongsToMany(AttributeValue::class, 'attribute_value_item');
...
...相关的多对多模型也是如此。
此外,我必须使用->syncWithoutDetaching([$item->id])
而不是->attach($item->id)
.
关于php - Laravel 5.5 枢转多对多仅保存一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47009535/