php - Laravel 5.5 枢转多对多仅保存一次

标签 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);
        }

    }

属性值

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

相关文章:

Laravel 5.5 : Testing with DatabaseMigrations deletes all tables

php - Laravel 5.3 日期验证器 : equal to or after start_date

php - 如何解析php中的动态_POST变量

MySQL 根据一列降序数字获取一系列值,然后随机化该范围

php - ("SQLSTATE[HY000] [1045] Access denied for user ' root' @'localhost' (使用密码 : NO)")

php - Opera Mini 和 PHP session

php - 内置对 PHP 集合的支持?

javascript - 在本地服务器而非实时服务器上发送 AJAX/PHP 表单

php - mysql_fetch_array 未获取完整数据?

MYSQL 两个大表之间的联合