laravel 是否可以延长迁移?如果可以,这是一个好的做法吗?

xfyts7mz  于 2023-01-06  发布在  其他
关注(0)|答案(2)|浏览(101)

我有两个在表结构方面相同的模型,但我希望将它们分开,以便利用类似下面这样的功能:
第一个月
我的目标是通过这两个模型的迁移扩展一个父迁移,即使它们是空的,也是出于上述原因。而且,我实在无法忍受在两个迁移文件之间复制和粘贴它们的结构。
以下是父迁移:

use Illuminate\Database\Migrations\Migration;

class CreateParentModelTable extends Migration
{
     /**
      * Run the migrations.
      *
      * @return void
      */
      public function up()
      {
          Schema::create('parent_model', function (Blueprint $table) {
              $table->bigIncrements('id');
              $table->timestamps();
          });
      }

      /**
      * Reverse the migrations.
      *
      * @return void
      */
      public function down()
      {
          Schema::dropIfExists('parent_model');
      }
}

下面是第一个模型迁移:

use App\Database\Migrations\CreateParentModelTable;

class CreateFirstModelTable extends CreateParentModelTable
{
    /**
    * Run the migrations.
    *
    * @return void
    */
    public function up()
    {
        Schema::create('first_model', function (Blueprint $table) {
            //
        });
    }

    /**
    * Reverse the migrations.
    *
    * @return void
    */
   public function down()
   {
       Schema::dropIfExists('first_model');
   }
}

当然,第二个模型迁移是相同的,现在......我知道这段代码不能工作,因为应该有一些东西实际上拉入父模型迁移,因为扩展它的类是不够的,但是第一个问题是我收到了一个奇怪的错误:

Class 'Database\Migrations\CreateParentModelTable' not found

为什么?除此之外,这篇文章的真实的问题是什么?

**EDIT:**Laravel自动添加的 CreateParentModelTable 前面的时间戳在导入时无法使用,所以我尝试了这种方式。
**实用的解决方案:**我刚刚创建了两个迁移,因为我确信它们有两种不同的用途,即使方式相同。

6rqinv9w

6rqinv9w1#

为此,您不一定需要两个迁移文件。简单地说,迁移是以某种方式修改数据库的一批操作。您必须自己决定在迁移中更改数据库的哪些部分。确实“建议”每个表使用一个迁移文件,但如果在给定的方案中有意义,您也可以采取不同的做法。
如果操作正确,您的迁移类继承方法将正常工作:

class CreateParentModelTable
{
    public function up()
    {
        Schema::create($this->table, function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

   public function down()
   {
       Schema::dropIfExists($this->table);
   }
}

class CreateFirstModelTable extends CreateParentModelTable
{
    protected $table = 'first_model';
}

class CreateSecondModelTable extends CreateParentModelTable
{
    protected $table = 'second_model';
}

另一种方法是使用带有相同选项的相同闭包在同一迁移文件中创建两个表:

public function up()
{
    $tableOptions = function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->timestamps();
    };

    Schema::create('first_model', $tableOptions);
    Schema::create('second_model', $tableOptions);
}

public function down()
{
    Schema::dropIfExists('second_model');
    Schema::dropIfExists('first_model');
}

另一个解决方案是通过创建一个可以以多态方式存储两个表的表来避免创建两个相等的表:

class CreatePolymorphicModelTable
{
    public function up()
    {
        Schema::create('polymorphic_model', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->enum('type', ['first', 'second']);
            $table->timestamps();
        });
    }

   public function down()
   {
       Schema::dropIfExists('polymorphic_model');
   }
}

根据表的类型(即它是否是1:n关系中的子表),遵守Laravel官方文档中描述的多态表和关系准则是有意义的。

c9qzyr3d

c9qzyr3d2#

我有一个类似的场景,我有许多表,其中将有一些共同的列。我想创建一个'基地'迁移,可用于添加这些共同的列。
我在migrations文件夹中创建了一个BaseMigration.php类,并在我的迁移文件中进行了扩展,但遇到了同样的错误,即无法找到该类。
最后我发现如果我把BaseMigration放到app目录下的一个子文件夹中,命名空间类似App\DatabaseHelpers,我就可以在迁移中导入和使用它。所以,可能是数据库或迁移文件夹有什么奇怪的地方阻止了文件被找到?
对于任何感兴趣的人,我添加了如下方法的公共列:

// BaseMigration.php

    protected function addCommonColumns(Blueprint $table): Blueprint
    {
        $table->id();
        $table->uuid('internal_id');
        $table->string('original_id');
        $table->string('common_reference');

        return $table;
    }

然后在实际的迁移文件中,我从BaseMigration调用该方法,传入$table变量,该变量将被返回。

// actual migration file

use App\DatabaseHelpers\BaseMigration;

return new class extends BaseMigration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('some_table', function (Blueprint $table) {
            $this->addCommonColumns($table);
            // add other columns as normal
    ...

这意味着我可以有不同的迁移,但有一些共同的字段。这也可能只通过导入到迁移文件中的帮助类来完成,而不是通过扩展基类。

相关问题