vendredi 5 avril 2019

Populate table after running a migration

Background:

In my application, Users can own Files. It used to be that a File belongs to a single User, so I used a one-to-many relationship. Now, the requirements have changed, and my relationship needs to become many-to-many.

Previously, the data structure looked like this:

files
(
  id,
  user_id
  ...
);

and the new data structure looks like this:

files
(
  id,
  ...
);

file_user
(
  id,
  file_id,
  user_id,
);

Problem:

I created a migration to change my data structure, like this:

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

        $table->string('file_id', 36);
        $table->string('user_id', 36);
    });
}

Then, I set up the relationship in the corresponding models. Now i need to convert the old data into the new data structure. That means taking all the existing Files, and creating a new record in the file_user table. The code itself is simple:

foreach(File:all() as $file) { 
    $file->users()->attach($file->user_id);
}

I want to run this code alongside the migration, so that after running the migration, the table will populate. However, when I try to put it directly in the migration file like this:

public function up()
{
    // create table
    Schema::create('file_user', function (Blueprint $table) {
        $table->increments('id');
        $table->timestamps();

        $table->string('file_id', 36);
        $table->string('user_id', 36);
    });

    // convert old data
    foreach(File:all() as $file) { 
        $file->users()->attach($file);
    }
}

I get an exception: PDOException: SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "file_user" does not exist. It seems like the table has not been created yet at the time when the code is trying to run.

Question:

Is there a way that I can put the conversion code inside the migration file to make it work like expected? Or is there a better way to achieve this?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire