Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added Doctrine migration creation task. Updated read me.

Signed-off-by: Taylor Otwell <taylorotwell@gmail.com>
  • Loading branch information...
commit 1e0f2ed3a2f358234dd05c594aeb40d4d0bddfb2 1 parent 36e9c44
@taylorotwell taylorotwell authored
View
168 migration.php
@@ -0,0 +1,168 @@
+<?php namespace Doctrine;
+
+use Laravel\IoC, Laravel\Bundle, Laravel\Database as DB;
+
+abstract class Migration {
+
+ /**
+ * The Doctrine Entity Mananger.
+ *
+ * @var Doctrine\ORM\EntityManager
+ */
+ protected $em;
+
+ /**
+ * The Doctrine Schema Mangager.
+ *
+ * @var Doctrine\DBAL\Schema\AbstractSchemaManager
+ */
+ protected $sm;
+
+ /**
+ * The current database schema ready for changes.
+ *
+ * @var Doctrine\DBAL\Schema\Schema
+ */
+ protected $schema;
+
+ /**
+ * The original schema before any changes were made.
+ *
+ * @var Doctrine\DBAL\Schema\Schema
+ */
+ protected $current;
+
+ /**
+ * Create a new HelpSpot Migration instance.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ Bundle::start('doctrine');
+
+ $this->em = IoC::resolve('doctrine::manager');
+
+ $this->sm = $this->em->getConnection()->getSchemaManager();
+ }
+
+ /**
+ * Execute the migration "up" command.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ // First we need to get the current databsae schema and then make
+ // a clone of it that can be modified by the migration and then
+ // compared to the original schema using Doctrine.
+ $this->current = $this->sm->createSchema();
+
+ $this->schema = clone $this->current;
+
+ // The change method will modify the schema object to alter the
+ // schema nad then once it has run we can get the "difference"
+ // SQL from doctrine and run it against the database.
+ $this->change();
+
+ $this->run($this->get_difference($this->current, $this->schema));
+
+ // After a migration has run, we serialize the original schema
+ // and store it in the database so we know how to rollback
+ // the changes that were made by this migration.
+ $this->save_schema($this->current);
+ }
+
+ /**
+ * Execute the migration "down" command.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ // When reversing a migration, we need to pull in the schema
+ // as it existed before this migration was run. We can then
+ // compare that schema to the current to rollback.
+ $this->previous = $this->get_previous();
+
+ $this->current = $this->sm->createSchema();
+
+ $this->run($this->get_difference($this->current, $this->previous));
+
+ $this->delete_schema();
+ }
+
+ /**
+ * Get the schema state from before this migration ran.
+ *
+ * @return Schema
+ */
+ protected function get_previous()
+ {
+ $connection = $this->em->getConnection();
+
+ $row = DB::table('laravel_schema')->where('name', '=', get_class($this))->first();
+
+ return unserialize($row->previous);
+ }
+
+ /**
+ * Get an array of the SQL needed to migrate from original to current schema.
+ *
+ * @param Doctrine\DBAL\Schema\Schema $from_schema
+ * @param Doctrine\DBAL\Schema\Schema $to_schema
+ * @return array
+ */
+ protected function get_difference($from_schema, $to_schema)
+ {
+ return $from_schema->getMigrateToSql($to_schema, $this->get_platform());
+ }
+
+ /**
+ * Run an array of SQL statements against the connection.
+ *
+ * @param array $sql
+ * @return void
+ */
+ protected function run($queries)
+ {
+ foreach ($queries as $query)
+ {
+ $this->em->getConnection()->query($query);
+ }
+ }
+
+ /**
+ * Store the pre-migration schema in the database.
+ *
+ * @param Doctrine\DBAL\Schema\Schema
+ * @return void
+ */
+ protected function save_schema($schema)
+ {
+ $data = array('name' => get_class($this), 'previous' => serialize($schema));
+
+ DB::table('laravel_schema')->insert($data);
+ }
+
+ /**
+ * Drop the pre-migration schema for the current migration.
+ *
+ * @return void
+ */
+ protected function delete_schema()
+ {
+ DB::table('laravel_schema')->where('name', '=', get_class($this))->delete();
+ }
+
+ /**
+ * Get the abstract database platform.
+ *
+ * @return Doctrine\DBAL\Platforms\AbstractPlatform
+ */
+ protected function get_platform()
+ {
+ return $this->em->getConnection()->getDatabasePlatform();
+ }
+
+}
View
15 migration_stub.php
@@ -0,0 +1,15 @@
+<?php
+
+class {{class}} extends Doctrine\Migration {
+
+ /**
+ * Make changes to the database.
+ *
+ * @return void
+ */
+ public function change()
+ {
+ //
+ }
+
+}
View
29 migrations/2012_03_03_033717_create_schema_table.php
@@ -0,0 +1,29 @@
+<?php use Laravel\Database\Schema;
+
+class Doctrine_Create_Schema_Table {
+
+ /**
+ * Make changes to the database.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create('laravel_schema', function($table)
+ {
+ $table->string('name')->primary();
+ $table->text('previous');
+ });
+ }
+
+ /**
+ * Revert the changes to the database.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('laravel_schema');
+ }
+
+}
View
49 readme.md
@@ -8,7 +8,54 @@
Add the following to your **application/bundles.php** file:
- 'doctrine' => array('auto' => true),
+ 'doctrine' => array(
+ 'auto' => true,
+ 'autoloads' => array(
+ 'map' => array(
+ 'Doctrine\Migration' => '(:bundle)/migration.php',
+ ),
+ ),
+ ),
+
+### Doctrine Migration Wrapper
+
+This bundle includes a custom **Doctrine\Migration** class that integrates with the Laravel migration CLI. If you wish
+to use this class, be sure to run the following command before writing Doctrine migrations:
+
+ php artisan migrate doctrine
+
+This will create a special table on your database used to store Doctrine schema information. Now you can extend this
+class in your migrations like so:
+
+ class Create_Users_Table extends Doctrine\Migration {
+
+ //
+
+ }
+
+When writing Doctrine migrations, you do not need to create an "up" and "down" method. You only need to create a
+"change" method which should be the equivalent of the "up" action. The Doctrine migration will intelligently
+reverse this change command when rolling back migrations!
+
+To create a Doctrine migration, you can use the following task:
+
+ php artisan doctrine::migrate:make migration_name
+
+In your Doctrine migrations, you may work on your database schema using the Doctrine schema building tools.
+For more information, consult the [Docrine schema documentation](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/schema-representation.html).
+
+ class Create_Users_Table extends Doctrine\Migration {
+
+ public function change()
+ {
+ $table = $this->schema->createTable('users');
+
+ $table->addColumn('id', 'integer', array('autoincrement' => true));
+
+ $table->addColumn('name', 'string');
+ }
+
+ }
### Doctrine CLI
View
70 tasks/migrate.php
@@ -0,0 +1,70 @@
+<?php
+
+use Laravel\Str;
+use Laravel\File;
+use Laravel\Bundle;
+
+class Doctrine_Migrate_Task {
+
+ /**
+ * Create a new Doctrine migration.
+ *
+ * @param array $arguments
+ * @return void
+ */
+ public function make($arguments)
+ {
+ if (count($arguments) == 0)
+ {
+ throw new \Exception("I need to know what to name the migration.");
+ }
+
+ list($bundle, $migration) = Bundle::parse($arguments[0]);
+
+ // The migration path is prefixed with the date timestamp, which
+ // is a better way of ordering migrations than a simple integer
+ // incrementation, since developers may start working on the
+ // next migration at the same time unknowingly.
+ $prefix = date('Y_m_d_His');
+
+ $path = Bundle::path($bundle).'migrations'.DS;
+
+ // If the migration directory does not exist for the bundle,
+ // we will create the directory so there aren't errors when
+ // when we try to write the migration file.
+ if ( ! is_dir($path)) mkdir($path);
+
+ $file = $path.$prefix.'_'.$migration.EXT;
+
+ File::put($file, $this->stub($bundle, $migration));
+
+ echo "Great! New migration created!";
+
+ // Once the migration has been created, we'll return the
+ // migration file name so it can be used by the task
+ // consumer if necessary for futher work.
+ return $file;
+ }
+
+ /**
+ * Get the stub migration with the proper class name.
+ *
+ * @param string $bundle
+ * @param string $migration
+ * @return string
+ */
+ protected function stub($bundle, $migration)
+ {
+ $stub = File::get(Bundle::path('doctrine').'migration_stub'.EXT);
+
+ $prefix = Bundle::class_prefix($bundle);
+
+ // The class name is formatted simialrly to tasks and controllers,
+ // where the bundle name is prefixed to the class if it is not in
+ // the default "application" bundle.
+ $class = $prefix.Str::classify($migration);
+
+ return str_replace('{{class}}', $class, $stub);
+ }
+
+}
Please sign in to comment.
Something went wrong with that request. Please try again.