eddy1992's avatar

Create columns in a table dynamically

Hi I want to know whether its possible to create columns dynamically in a table. For example If I have table named car and I have two columns , car_name, car_year and later on some condition I want to add columns dynamically like car_tyre, car_insurance in the table. If this is possible please let me know. Thanks.

0 likes
10 replies
Dunsti's avatar

Just do it, like you do in migrations:

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;

...

Schema::table('cars', function (Blueprint $table) {
    $table->string('car_tyre');
});
1 like
Cronix's avatar
Cronix
Best Answer
Level 67

That is code lol. You can use Schema outside of migrations...

You could make it as dynamic as you want.

$type = 'string';
$length = 20;
$fieldName = 'car_tyer';

Schema::table('cars', function (Blueprint $table) use ($type, $length, $fieldName) {
    $table->$type($fieldName, $length);
});
1 like
genyded's avatar

@cronix and all... The current answer is great for just the base column and I know this is a bit old, but how could one account for things like unique(), unsigned(), nullable(), and so on in this type of scenario dynamically on a per column basis? Some columns may have them and others not.

genyded's avatar

OK, we figured hopefully we'd hopefully save at least one other person at some point the hours we spent digging into this. This isn't the end all - be all, but it should be enough to give you a pretty good idea of what is needed for something like this in a bit more detail. We're using mostly methods from the ColumnDefininition class.

We have the fields hard-coded here, but in the real world they are pulled from the DB. If you comment out the die and dump below and your DB is setup, you should see the table matches 100%. If you don't want to actually create it, just look at the dd() output. Hope this helps someone some day,

public function createDynamic($table_name = 'test', $timestamps = true)
    {
      $fields = [
        ['name' => 'id', 'type' => 'increments', 'size' => null, 'index' => null, 'nullable' => 0, 'unsigned' => 0, 'default' => null],
        ['name' => 'field_1', 'type' => 'string', 'size' => 300, 'index' => null, 'nullable' => 0, 'unsigned' => 0, 'default' => null],
        ['name' => 'field_2', 'type' => 'string', 'size' => null, 'index' => 'unique', 'nullable' => 1, 'unsigned' => 0, 'default' => null],
        ['name' => 'field_3', 'type' => 'integer', 'size' => null, 'index' => null, 'nullable' => 0, 'unsigned' => 1, 'default' => null],
        ['name' => 'field_4', 'type' => 'integer', 'size' => null, 'index' => null, 'nullable' => 0, 'unsigned' => 0, 'default' => 123]
      ];

      Schema::create($table_name, function (Blueprint $table) use($fields, $timestamps){
        if (count($fields) > 0) {
          $cnt = 0;
          foreach ($fields as $field) {
            if($field['size'] > 0) {
              $table->{$field['type']}($field['name'], $field['size']);
            } else {
              $table->{$field['type']}($field['name']);
            }
            if($field['nullable'] > 0) {
              $table->getColumns()[$cnt]->nullable();
            }
            if($field['unsigned'] > 0) {
              $table->getColumns()[$cnt]->unsigned();
            }
            if(strlen($field['default']) > 0) {
              $table->getColumns()[$cnt]->default($field['default']);
            }
            if(strlen($field['index']) > 0) {
              switch ($field['index']) {
                case 'unique':
                  $table->getColumns()[$cnt]->unique();
                  break;
                case 'index':
                  $table->getColumns()[$cnt]->index();
                  break;
                case 'primary':
                  $table->getColumns()[$cnt]->primary();
                  break;
              }
            }
            $cnt++;
          }
        }
        if($timestamps) {
          $table->timestamps();
        }
        dd($table);
      });
    }
1 like
jaseofspades88's avatar

It's a migration file, that is only ever run once (apart from during development). Why complicate something that simply allows you to scaffold out your database? If the only reason is so you only have to update the array the migration iterates upon, well then this is still pointless because you should simply create a new migration each time anyway.

Fewzen's avatar

There are many reasons why you might want to complicate migrations....

I have a client requirement who wants to dynamically import a CSV file into a model which does not exist. Uploading the CSV file will create the migration dynamically....

Otherwise, the client would have to come to us to import a new file rather than be able to do it themself.

1 like

Please or to participate in this conversation.