New to Migrations in 1.1

Posted on October 18, 2008 by jwage


In Doctrine 1.1 migrations are much easier to work with. In addition to the increased stability we have enhanced the migrations in a few ways to simplify the use of them dramatically.

We have introduced the following features.

  • Diff Tool - Generate migration classes by simply changing your schema and generating the migrations.
  • Down Automation - Doctrine now has the ability to automate the down of of a migration call.

Generating Migrations

Imagine you have the following starting schema.

[yml]
---
User:
  columns:
    username: string(255)
    password: string(255)

Build your initial models from the schema.

$ ./doctrine generate-models-yaml

Now we want to enhance our schema to add some new columns as well as a new model with the following schema.

[yml]
---
User:
  columns:
    username: string(255)
    password: string(255)
    email_address: string(255)

Phonenumber:
  columns:
    user_id: integer
    phonenumber: string(25)
  relations:
    User:
      onDelete: CASCADE
      foreignAlias: Phonenumbers

Now by simply changing our schema we can generate the migrations required to upgrade our database.

$ ./doctrine generate-migrations-diff

Now in your migrations directory you will see 3 migration classes created for you.

1224273485_add_user.php

<?php
<?php
/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class AddUser extends Doctrine_Migration_Base
{
  public function up()
  {
    $this->createTable('up', 'user', array('id' => array('type' => 'integer', 'length' => 8, 'autoincrement' => true, 'primary' => true), 'username' => array('type' => 'string', 'length' => 255), 'password' => array('type' => 'string', 'length' => 255)), array('indexes' => array(), 'primary' => array(0 => 'id')));
  }

  public function down()
  {
    $this->dropTable('up', 'user');
  }
}

1224273485_version1.php

<?php
<?php
/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class Version1 extends Doctrine_Migration_Base
{
  public function up()
  {
    $this->createTable('up', 'phonenumber', array('id' => array('type' => 'integer', 'length' => 8, 'autoincrement' => true, 'primary' => true), 'user_id' => array('type' => 'integer', 'length' => 8), 'phonenumber' => array('type' => 'string', 'length' => 25)), array('indexes' => array(), 'primary' => array(0 => 'id')));
    $this->addColumn('up', 'user', 'email_address', '255', 'string', array ());
  }

  public function down()
  {
    $this->dropTable('up', 'phonenumber');
    $this->removeColumn('up', 'user', 'email_address');
  }
}

1224273486_version2.php

<?php
<?php
/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class Version2 extends Doctrine_Migration_Base
{
  public function up()
  {
    $this->addIndex('up', 'phonenumber', 'phonenumber_user_id_user_id', array('fields' => array(0 => 'user_id')));
    $this->createForeignKey('up', 'phonenumber', array('name' => 'phonenumber_user_id_user_id_idx', 'local' => 'user_id', 'foreign' => 'id', 'foreignTable' => 'user', 'onUpdate' => NULL, 'onDelete' => 'CASCADE'));
  }

  public function down()
  {
    $this->removeIndex('up', 'phonenumber', 'phonenumber_user_id_user_id', array('fields' => array(0 => 'user_id')));
    $this->dropForeignKey('up', 'phonenumber', array('name' => 'phonenumber_user_id_user_id_idx', 'local' => 'user_id', 'foreign' => 'id', 'foreignTable' => 'user', 'onUpdate' => NULL, 'onDelete' => 'CASCADE'));
  }
}

Down Automation

In addition to Doctrine being able to generate migrations based on your schema changes, you can now easily automate the down of most methods. The last migration class could be simplified a lot by doing the following.

<?php
<?php
/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class Version2 extends Doctrine_Migration_Base
{
  public function migrate($direction)
  {
    $this->addIndex($direction, 'phonenumber', 'phonenumber_user_id_user_id', array('fields' => array(0 => 'user_id')));
    $this->createForeignKey($direction, 'phonenumber', array('name' => 'phonenumber_user_id_user_id_idx', 'local' => 'user_id', 'foreign' => 'id', 'foreignTable' => 'user', 'onUpdate' => NULL, 'onDelete' => 'CASCADE'));
  }
}

Notice that in this example we only have one method named migrate() which receives a direction. Most API methods are easy to automate the opposite down so when migrate is called with \$direction = 'down' then the index and foreign key will be dropped instead of added.