2017-10-30 13 views
0

多対多リレーションではアイテムごとにデータを1回しか保存していないため、複数のアトリビュートを複数のアイテムにアタッチするときに間違いを見つけられません。ここでLaravel 5.5多対多セーブを一度だけ実行する

は私のモデルは以下のとおりです。

項目

<?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の

ご覧のとおり、$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(); 
     } 
    } 

...とジェフリー・ウェイの

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とともにピボットテーブルに格納されます。しかし、時にはブランドのような属性を持っている2番目、3番目、n番目のアイテム(Nikeなどと言ってみましょう)では、リレーションはスキップされ、保存されません。

これは本当に面白いですし、正直に私の狂気を少しドライブします。

答えて

1

申し訳ありませんが、ピボットテーブルに名前を付けるための正しい規則に従わなかったようです。

したがって、2番目の引数belongsToMany()を追加すると、それが解決されました。

これは、それが見えるように持っているものです。

... 

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

... 

...、あまりにも関連する多対多のモデルに同じ。

さらに、->attach($item->id)の代わりに->syncWithoutDetaching([$item->id])を使用しなければなりませんでした。

関連する問題