Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ahoi's avatar
Level 5

$table->enum('type', ...)->change(); fails with Postgres

Hi there,

I got a table which has an enum column. No the enum got a few more cases and I wanted to update that with a migration:

$table->enum('type', CustomerType::values())->change();

But this fails:

SQLSTATE[42601]: Syntax error: 7 ERROR:  syntax error at or near "check"
LINE 1: ...ustomers" alter column "type" type varchar(255) check ("ty...
                                                             ^ (Connection: pgsql, SQL: alter table "customers" alter column "type" type varchar(255) check ("type" in (...)), alter column "type" set not null, alter column "type" drop default, alter column "type" drop identity if exists)
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:568
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:809
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:776
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:557
at vendor/laravel/framework/src/Illuminate/Database/Schema/Blueprint.php:119
at vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php:618
at vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php:460
at vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:361

I checked the docs, but there is no hint that change() would not work with enums.

0 likes
3 replies
LaryAI's avatar
Level 58

The issue here is that Laravel's $table->enum(...)->change() is not fully supported on PostgreSQL. Unlike MySQL, PostgreSQL does not have a native ENUM type in Laravel migrations—Laravel emulates it using a VARCHAR column with a CHECK constraint. However, Laravel's schema builder does not handle updating the CHECK constraint when you use ->change() on an enum column. This results in the syntax error you see.

How to fix it:

You need to manually drop the old check constraint and add a new one with the updated values. Here’s how you can do it in a migration:

  1. Find the name of the existing check constraint.
    By default, Laravel does not name the check constraint, so PostgreSQL gives it an auto-generated name (e.g., customers_type_check). You can find it with:

    SELECT conname
    FROM pg_constraint
    WHERE conrelid = 'customers'::regclass AND contype = 'c';
    
  2. Write a raw migration to drop and recreate the constraint.

    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Support\Facades\DB;
    
    class UpdateCustomerTypeEnum extends Migration
    {
        public function up()
        {
            // Drop the old check constraint
            DB::statement('ALTER TABLE customers DROP CONSTRAINT IF EXISTS customers_type_check');
    
            // Add the new check constraint with the updated enum values
            DB::statement("ALTER TABLE customers ADD CONSTRAINT customers_type_check CHECK (type IN ('value1', 'value2', 'new_value', ...))");
        }
    
        public function down()
        {
            // Rollback: drop the new constraint and add the old one back
            DB::statement('ALTER TABLE customers DROP CONSTRAINT IF EXISTS customers_type_check');
            DB::statement("ALTER TABLE customers ADD CONSTRAINT customers_type_check CHECK (type IN ('value1', 'value2', ...))");
        }
    }
    

    Replace 'value1', 'value2', 'new_value', ... with your actual enum values.

Note:

  • If you use a custom constraint name, adjust accordingly.
  • If you want to automate the enum values, you can use implode on your enum class values.

Summary:
Laravel's enum(...)->change() does not work on PostgreSQL because it cannot update the CHECK constraint. You need to manually drop and recreate the constraint using raw SQL in your migration.

1 like
martinbean's avatar

@ahoi This is one of the drawbacks of enum-type columns: you can‘t modify them after creating them, you have to drop the re-create the entire column.

Instead, just use a string column, and enforce the cases in your code using a PHP enumeration.

Please or to participate in this conversation.