Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Migration - Update Enum Options

Tags:

laravel

I'm trying to add an enum option to a table (without losing the current dataset) using the schema builder.

The only thing I've really been able to find about column alteration is http://www.flipflops.org/2013/05/25/modify-an-existing-database-column-in-a-laravel-migration/ and I believe that was written for Laravel3.

Even so, I tried using the DB::query('ALTER TABLE ...'); command but it errored out with call_user_func_array() expects parameter 1 to be a valid callback, class 'Illuminate\Database\MySqlConnection' does not have a method 'query'.

DB::query("ALTER TABLE users CHANGE COLUMN permissions permissions ENUM('admin', 'user', 'candidate')"); 

I also tried doing this:

Schema::table('users', function ($table) {     $table->enum('permissions', array('admin', 'user', 'candidate'))->default('user'); }); 

but it errors out saying the column already exists.

What's the best way to do what I'm trying to do without losing all the data in that column?

like image 679
Lisa Avatar asked Aug 11 '14 19:08

Lisa


People also ask

What is enum variable?

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

What is enum in laravel?

Laravel Enum is a package by Ben Sampson that adds support for creating enums in PHP and includes a generator for Laravel. Here's an example of what an Enum class looks like using this package: 3namespace App\Enums; 5use BenSampo\Enum\Enum; 7final class UserType extends Enum.


2 Answers

Use the DB::statement method:

DB::statement("ALTER TABLE users CHANGE COLUMN permissions permissions ENUM('admin', 'user', 'candidate') NOT NULL DEFAULT 'user'"); 
like image 175
Joseph Silber Avatar answered Sep 21 '22 15:09

Joseph Silber


I have adapted Joseph's answer into a method you can add to your migration and then call with an array of values instead of hardcoding them inside of a statement. It doesn't have any fancy handling of values with quotes in them, so please only use sensible values with it, or modify it for yourself.

private function setEnumValues($table, $column, array $values, $nullable = false, $default = null) {     $quotedValues = collect($values)         ->map(function ($value) {             return "'${value}'";         })         ->join(', ');      $suffix = '';      if (!$nullable) {         $suffix .= ' NOT NULL';     }      if ($default) {         $suffix .= " DEFAULT '${default}'";     }      $statement = <<<SQL ALTER TABLE ${table} CHANGE COLUMN ${column} ${column} ENUM(${quotedValues}) ${suffix} SQL;      \Illuminate\Support\Facades\DB::statement($statement); } 

You might use it in a migration like so:

<?php  use Illuminate\Database\Migrations\Migration;  class AddQueuedStatusToPaymentsTable extends Migration {     /**      * Run the migrations.      *      * @return void      */     public function up()     {         // Add the new 'queued' value          $this->setEnumValues(             'payments',             'status',             [                 'queued',                 'processing',                 'successful',                 'failed',             ],             false, // Not nullable             'queued' // Mark it as the default for all new payments         );     }      /**      * Reverse the migrations.      *      * @return void      */     public function down()     {         // Remove the new 'queued' value                  $this->setEnumValues(             'payments',             'status',             [                 'processing',                 'successful',                 'failed',             ],             false, // Not nullable             'processing' // Set the default back to processing for all new payments         );     }      private function setEnumValues($table, $column, array $values, $nullable = false, $default = null)     {         $quotedValues = collect($values)             ->map(function ($value) {                 return "'${value}'";             })             ->join(', ');          $suffix = '';          if (!$nullable) {             $suffix .= ' NOT NULL';         }          if ($default) {             $suffix .= " DEFAULT '${default}'";         }          $statement = <<<SQL ALTER TABLE ${table} CHANGE COLUMN ${column} ${column} ENUM(${quotedValues}) ${suffix} SQL;          \Illuminate\Support\Facades\DB::statement($statement);     } }  
like image 25
mitchdav Avatar answered Sep 17 '22 15:09

mitchdav