我的多对多关系只为每个项目保存一次数据,我找不到将多个属性附加到多个项目时可能会犯的错误。
以下是我的模特:
物品
<?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);
}
}
的AttributeValue
<?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个项目,它有时具有相同的属性,如品牌(让我们说耐克或类似的东西),这些关系被跳过,而不是保存。
这真是好奇,老老实实地让我疯狂了一点。
答案 0 :(得分:1)
好吧,因为我似乎没有遵循命名数据透视表的正确惯例。
因此添加第二个参数belongsToMany()
方法解决了它。
这就是它的样子:
...
return $this->belongsToMany(AttributeValue::class, 'attribute_value_item');
...
......对于相关的多对多模型也是如此。
此外,我必须使用->syncWithoutDetaching([$item->id])
代替->attach($item->id)
。