Kenneth_H's avatar

Migration that modifies existing database

Hi I have an app which am I porting to Laravel. The problem is I want to provide users of the previous version with the option to run an artisan command and then Laravel will run some special migrations that would then change the existing database schema to work with new code. I have created the migrations in a seperate folder, but when I try to run a migration it says that there is nothing to migrate. Here is the up() method from one of the migrations:

    public function up()
    {
        Schema::table('maillog', function ($table) {
            log()->debug('Start migration');
            if($table->engine == 'MyISAM')
            {
                log()->debug('MIGRATE: Table is MyISAM');
                $table->engine = 'InnoDB';
                log()->debug('MIGRATE: Engine changed to InnoDB');
                $table->dropPrimary('id');
                log()->debug('MIGRATE: Old primary key dropped');
                $table->renameColumn('id', 'mailwatch_id');
                log()->debug('MIGRATE: Old ID column renamed');
                $table->uuid('id')->nullable();
                log()->debug('MIGRATE: UUID column created');
            }
        });
        log()->debug('MIGRATE: Start to fill in the new UUID\'s');
        foreach (\MailLight\Models\MailLogEntry::all() as $item)
        {
            $item->id = (string)\Ramsey\Uuid\Uuid::uuid4();
            $item->save();
        }
        log()->debug('MIGRATE: UUID update completed');
        Schema::table('maillog', function ($table) {
            log()->debug('MIGRATE: Start final stage of modification');
            $table->uuid('id')->change();
            log()->debug('MIGRATE: UUID set to NOT NULL');
            $table->primary('id');
            log()->debug('MIGRATE: UUID set as primary key');
        });
    }

Basically what I want is to make sure that the table uses InnodDB instead of MyISAM, since some of the older installations were actually using MyISAM as the database table engine. Then I want to remove the existing ID column as a primary key and create a new UUID column. Once the UUID column has been created I want to autogenerate a new UUID before setting the column as the primary key and then set it as the primary key.

I run the following command in the root of my Laravel app to trigger the above migration:

php artisan migrate --path=resources/database/2016_12_20_194837_migrate_maillog.php

I have PHP 5.6.25

How can I get the result described above and am I doing anything wrong?

0 likes
4 replies
bobbybouwmann's avatar

I think you need to provide a directory instead of a file for the --path option, but I could be wrong.

Another issue might be that you don't have a migrations table in your database. And if you have a table check if the name of the current migration class already exists in there. If that is the case, the migration has already ran.

Kenneth_H's avatar

Hi I tried to run

php artisan migrate:install

To install the migrations table and then run the migration. Still says nothing to migrate When I run

php artisan migrate --path=resources/database/

I get this error

[Symfony\Component\Debug\Exception\FatalErrorException]  
  parse error

I do not really know why this happens, but otherwise I might have to write a SQL-script that runs a raw query to do the changes, but that would leave me in a situation where I have to write a script for each supported database type.

Kenneth_H's avatar
Kenneth_H
OP
Best Answer
Level 16

I seem to have found the solution. I forgot to typehint the arguments fassed to the closure. I wrote

Schema::table('maillog', function ($table) {

But I should have written

Schema::table('maillog', function (Blueprint $table) {
bobbybouwmann's avatar

Aah.. Well it shouldn't be an issue, but glad you fixed it ;)

Please or to participate in this conversation.