Laravel 5.5只能将多对多保存转移一次

时间:2017-10-30 06:55:16

标签: php mysql laravel eloquent pivot

我的多对多关系只为每个项目保存一次数据,我找不到将多个属性附加到多个项目时可能会犯的错误。

以下是我的模特:

物品

<?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个项目,它有时具有相同的属性,如品牌(让我们说耐克或类似的东西),这些关系被跳过,而不是保存。

这真是好奇,老老实实地让我疯狂了一点。

1 个答案:

答案 0 :(得分:1)

好吧,因为我似乎没有遵循命名数据透视表的正确惯例。

因此添加第二个参数belongsToMany()方法解决了它。

这就是它的样子:

...

return $this->belongsToMany(AttributeValue::class, 'attribute_value_item');

...

......对于相关的多对多模型也是如此。

此外,我必须使用->syncWithoutDetaching([$item->id])代替->attach($item->id)