PHPexp logo PHPexp

Change a model with a uuid primary key to an auto-incrementing integer

Published on

If you have an existing model with a uuid primary key, and you'd like to change it to an auto-incrementing integer, then this post will get you most of the way there. This post isn't complete, it doesn't mention how to deal with foreign keys and morphables. You're on you're own for that one.

class ChangeUserPrimaryKeyType extends Migration
{
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropPrimary('id');

            $table->renameColumn('id', 'uuid');

            $table->unique('uuid');
        });

        Schema::table('users', function (Blueprint $table) {
            $table->unsignedBigInteger('id')->after('uuid')->nullable();
        });

        // If you're using soft-deletes, add `withTrashed()`
        foreach (User::orderBy('created_at')->pluck('uuid') as $i => $uuid) {
            User::where('uuid', $uuid)->update(['id' => $i + 1]);
        }

        Schema::table('users', function (Blueprint $table) {
            $table->unsignedBigInteger('id')->nullable(false)->change();

            $table->primary('id');
        });

        Schema::table('users', function (Blueprint $table) {
            $table->unsignedBigInteger('id', autoIncrement: true)->change();
        });

        // Optional: move the uuid column after the new id column 
        DB::statement('ALTER TABLE users MODIFY COLUMN uuid char(36) AFTER id');
    }
}

After changing the primary key, you can remove these attributes from your model:

class User extends Model
{
    protected $keyType = 'string';

    public $incrementing = false;
}

Don't forget to update any route model bindings if you still want to use the uuid:

// Before: this used the uuid
Route::get('/profile/{user}', [UsersController::class, 'show']);

// After: if you still want to use the uuid
Route::get('/profile/{user:uuid}', [UsersController::class, 'show']);

Level up your Laravel deployments

If you aren't happy with your current deployment strategy for your Laravel apps, check out my premium deployment script.

Deploy with GitHub Actions Deploy with GitLab CI/CD