Kris01's avatar

Laravel Add Fields On Migration

Hello All,

I need to add a field on a table in my database, but the problem is that my app is already live and I have some data. I want to add the 'slug' field inside 'users' table, and even tho I use the add migration, the 'slug' in my already existing users will be empty, how can I solve this avoiding to manually go in my db and fill out the slugs of my existing users

0 likes
14 replies
Sinnbeck's avatar

You will need to add the slug. But set the new migration to add a new column with default slug = ''. Then in the same migration set the slug on all existing users

Kris01's avatar

@Sinnbeck I will add the field, that's no problem, but I will need to fill that field inside the existing users, I didn't understeand that part.

Sinnbeck's avatar

@Kris01 inside the up method, after adding the field, you can run an update on the database. Show the migration if in doubt

Kris01's avatar

@Sinnbeck let's say I have two users

USER TABLE
name     last_name
Jhon       Doe
Ambra    Lauren

Now I need to add a slug field, which can't be null. I am going to create the 'add' migration adding the field, but how can I popolate it on the already existing users?

In this case like this

USER TABLE
name     last_name    slug
Jhon       Doe				john-doe
Ambra    Lauren			ambra-lauren
Sinnbeck's avatar

@Kris01 you need to allow it to be null or have a default. No way around it. After it has been created and users are updated, you can remove nullable/default. Think of it as a 3 step process.

1 like
Kris01's avatar

@Sinnbeck Right, but do I have to go and manually update the database? Isn't there any other faster/better way?

Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

@Kris01 you can add it as part of the migration. Just add it in the up method after the adding of the column

Shivamyadav's avatar

@Kris01 try running this command

php artisan make:migration add_slug_to_users_table --table=users
Kris01's avatar

@Sinnbeck I did this, is this right?

Schema::table('listings', function (Blueprint $table) {
            $table->string('slug')->unique();
});

$listings = DB::table('listings');
foreach($listings as $listing){
    DB::table('listings')->where('id', $listing->id)->update(['slug'=>str_slug($listing->company_name)]);
};
Tray2's avatar

You could also make the slug a generated column, that way you generate the slug on the fly. Not sure how well that works with an index though.

Update: It works fine with an index on the generated column.

https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html

Here is an example

ALTER TABLE `authors`	ADD COLUMN `slug` VARCHAR(255)
AS(CONCAT(
		LOWER(`last_name`), '-', LOWER(`first_name`)
		)
   ) STORED;
1 like
illummina's avatar

Add in User model class:

public static function boot(): void
{
    parent::boot();

    self::creating(function ($model) {
        // here you can decide what unique field will be used as slug, for ex. email
        $model->slug = Str::slug($model->email);
    });

    self::updating(function ($model) {
        if (!$model->isDirty('email')) {
            $model->slug = Str::slug($model->email);
        }
    });
}

public function getRouteKeyName(): string
{
    return 'slug';
}

Create new migration to update table:

public function up(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('slug')->unique();
    });
}

public function down(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('slug');
    });
}

Run php artisan migrate

Please or to participate in this conversation.