I have to ask... why a separate table when you could just add a type column to the users table?
How to add a foreign ID column with a default when data exists
So let's say I have table users in production. Later I want to create table user_types. This table would be a reference table with id and name. First row ['id' => 1, 'name' => 'regular'] and second row ['id' => 2, 'name' => 'special'].
So I create a migration for the new table, and then another migration to add the new field into users table. There is my issue.
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->foreignId('user_type_id')->default(UserType::whereName('regular')->id);
$table->foreign('user_type_id')->references('id')->on('user_types');
});
}
So, of course at this point UserType::whereName('regular') is null. I could default to 0 or 1, but then creating the foreign fails anyway since the user_types table is not yet populated. The seeder is ready, and I have a script to run it automatically on deploy, but since migrations run one after the other, defining any kind of default would fail.
If I was to separate it into 2 migrations, run the first, run the seeder and then run the second one, then sure it would work. But I honestly find it a bit clumsy. I mean that forces me to commit the first part of the migrations to production, run the seeder, and only then commit the second. Feels wrong. Not a good practice at all.
Also, calling the seeder into the migration file is bad. Migrations are for structure, not data. That means also that in tests, that particular seeder shouldn't be called with all the others. Really don't want to do that.
Any idea?
@JerryBels My solution to the original question would be as Lary says, default it to one particular type (even if it is 'unset' and then run the process that sets the correct value on the record.
Please or to participate in this conversation.