【问题标题】:How to migrate from string column to foreign key pointing to row in other table with same string value in Laravel?如何在 Laravel 中从字符串列迁移到指向其他表中具有相同字符串值的行的外键?
【发布时间】:2019-03-20 15:04:06
【问题描述】:

我正在使用 Laravel 5.6,需要一些帮助来从已填充的表中迁移一列,以保留内容逻辑。有一个表 pages 包含一个名为 icon 的列,它接受 string 值。

例如:

Schema::create('pages', function (Blueprint $table) {
        $table->increments('id');
        ...
        $table->string('icon')->nullable();
}

pages 表已填充,icon 列可以为空,但并不总是使用。

创建了一个新的icons 表来存储所有可用的图标类。

例如:

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

如何将icon 列从pages 表迁移为指向icons 表行的外键,该行在name 列中具有相同的值,如果未填充,则为空?

【问题讨论】:

    标签: sql laravel laravel-5 foreign-keys migration


    【解决方案1】:

    我建议在这里使用多态 many-to-many 方法,以便 icons 可重复使用并且不需要一堆数据透视表,如果您希望 icons 在页面以外的其他内容上。

    Schema::create('icons', function(Blueprint $table) {
        $table->increments('id');
        $table->string('name');
    });
    
    Schema::create('iconables', function(Blueprint $table) {
        $table->integer('icon_id');
        $table->integer('iconables_id');
        $table->integer('iconables_type');
    });
    

    现在您只需要确定页面是否有现有的Icon。如果有,请保留对它们的引用,以便您可以插入它们:

    $pagesWithIcons = Page::whereNotNull('icon')->get();
    

    此时您需要在模型中定义多态关系:

    // icon
    
    class Icon extends Model
    {
        public function pages()
        {
             return $this->morphedByMany(Page::class, 'iconable');
        }
    }
    
    // page
    
    class Page extends Model
    {
        public function pages()
        {
             return $this->morphToMany(Icon::class, 'iconable');
        }
    }
    

    现在您只需要创建icons(回到我们的迁移中),然后在它们存在时附加它们:

    $pagesWithIcons->each(function(Page $page) {
        $icon = Icon::firstOrNew([
            'name' => $page->icon
        });
    
        $icon->pages()->attach($page);
    });
    

    上面是创建一个Icon 如果它不存在,或者如果它存在则查询它。然后将页面附加到icon。由于多态 many-to-many 关系只是在底层使用 belongsToMany() 方法,如果这不符合您的需求,您可以在闲暇时使用所有可用的操作。

    最后,从页面中删除您的 icons 列,您不需要它。

    Schema::table('pages', function(Blueprint $table) {
        $table->dropColumn('icon');
    });
    

    如果您只需要回填对单个 icon 的支持(因为 many-to-many 现在将返回一个数组关系),您可以将以下内容添加到您的 page 模型中:

    public function icon()
    {
        return $this->icons()->first();
    }
    

    抱歉,如有错别字,我是在手机上做的,所以可能有一些错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-28
      • 2018-12-31
      • 2015-03-31
      • 2017-10-28
      • 2019-01-12
      • 2017-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多