donglangtun1850 2017-10-30 06:55
浏览 103

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

My many-to-many relations are saving data only once for each items and I can not find the mistake I possibly did when attaching multiple attributes to multiple items.

Here are my models:

Item

<?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);
        }

    }

Attribute

<?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);
        }

    }

As you can see, I try to separate attribute and its values for better access to each values like $item->attributes() or $attribute->values().

My migrations look like this:

Item

<?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();
       }
   }

attributes

<?php
   ...
   class CreateAttributesTable extends Migration
   {

       public function up()
       {
            Schema::create('attributes', function ( Blueprint $table ) {
                $table->increments('id');
                $table->string('name');
                $table->timestamps();
       }
   }

attribute values

<?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();
       }
   }

...and last but not least, the pivot table created with Jeffrey Way's cool Laravel Extended Generators

attribute value item pivot

<?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' ]);
    });
       }
   }

I know, this is a lot of code but I think this is neccesary for helping me with this issue.

Imagine, I am getting objects for different items with attributes like brand, size, height etc.

When I try to attach them to my pivot table like

$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);
    }

Now, the when looping through the first item, everything works fine. All attribute ids are stored in the pivot table with the related item id. But for the second, third, nth item which has sometimes the same attributes like brand (let's say Nike or something like this) the relations are skipped and not beeing saved.

This is really curios and honestly drives my crazy a little bit.

  • 写回答

1条回答 默认 最新

  • duanli9569 2017-10-30 07:51
    关注

    Alright, as it seems I did not follow the right conventions for naming pivot tables.

    So adding the second argument belongsToMany()method solved it.

    This is what it has to look like:

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

    ...and the same for the related many-to-many models too.

    Additionally, I had to use ->syncWithoutDetaching([$item->id]) instead of ->attach($item->id).

    评论

报告相同问题?

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)