I'm about to start building an API for an existing app with the DB already in production. Functionality will slowly be ported to the API in the future and the app will become more "API-centric".
One of the main starting points is to adopt migrations and a build process. I have reservations on the best way to create migrations for an existing schema without breaking production when they are executed.
As we would like to move quickly with porting functionality over to the API, we ideally want to recreate our current schema as part of our build process and get some core unit tests in place - as opposed to just creating migrations for future changes.
This is where I become unsure as to the best place to start.
What is the best approach for a task like this?
Could the current schema be imported as our first migration?
Could this initial migration be wrapped in something like:
if ( App::environment() !== 'production' ) to ensure it isn't executed in a production environment?
Is it ok to exclude a migration for a particular environment or could this cause problems?
Is there maybe another approach or something stupidly simple I'm missing? :)
I created a tool not to long ago that will generate all the migrations for your current database schema. It also adds the newly created migrations to the migrations table, as the tables already exist. You can get it here: https://github.com/Xethron/migrations-generator
Secondly, I use the following line of code in my DatabaseSeeder, but you can add it to any function you wish to disable in production:
if (App::environment() === 'production') {
exit('Don\'t be stupid, this is a production server!!!');
}
It shouldn't be a problem if you stop execution by throwing an error or as I do above. If you don't, Laravel will believe the changes happened successfully and remove them from the migrations table, and cause errors when running your migrations. The only exception is if you exclude both the up and down code (But I can't see why you would want to do that)
Hope this helps.
I wouldn't suggest running migrations in production environment at all, but if you must then make a backup copy of the database first and also create a copy of the database locally and do the migration there then test to make sure it all works properly.
You could create your first migration and manually add all the schema layout to it. But I would actually do this in a few migrations to have each table as its own migration.
Since migrations are run from the CLI using artisan you can pass the environment and the database you want the migration to be run on:
artisan migrate --database="connectionName" --env="local"
There is no issue running migration on a particular environment besides what I stated above for production.
Remember to add all existing schema layouts from step 1 (the migration file name excluding the extension e.g. 2014_03_25_143340_AddCountriesTable) to the migrations table in the database, otherwise running the command in step 2 will throw errors about table already exist.
Hope this helps.
Related
I'm using database migrations with PHP symfony framework and I noticed that there are a lot of files, and when I build my project and every time many files (migrations) are executed.
What is best practice to manage migrations? Could I delete them and create only one database dump file, for database initiation?
I'm assuming you're using Doctrine Migrations to create these files. On dev you can always regenerate the database using the doctrine:schema:update command.
When setting up a new instance you can also use the doctrine:schema:create command which will also create the latest table definitions for you.
That brings us to your question; do you need to keep all the migrations? As long as you know that the migrations have been executed on outdated instances you can safely archive (my preferred option) or delete them as they will never be called again.
I would prefer to use migrations on production instead of doctrine:schema:update, because you can have some problems while updating process. It is always a better option IMO to keep an eye on what happens with the DB.
On development env you can easily use doctrine:schema:update command but you should use migrations on production. In some cases the command may brake the migrations (it happened to me a few times).
I'm working on a project that has a fairly complex database (150+ tables). In order to be able to maintain changes, I've decided to add migrations, preferably using Yii or Laravel.
Does anybody know, if it is possible to generate a initial migration from an existing database?
Creating it by hand would:
take for ever and
be very error-prone.
If there is no way, does anybody know a good PHP-based framework, that supports such functionality?
Instructions for accomplishing this in Yii:
Add your database connection settings to protected/config/console.php.
Run yiic migrate create initial to create the stub code for the migration.
Copy contents of this gist to protected/commands/InitialDbMigrationCommand.php.
Run yiic initialdbmigration 'name_of_your_database' > initial_migration.php to generate up() and down() methods for initial database migration.
Copy and paste up() and down() methods from initial_migration.php to the file created in the protected/migrations folder in step 2.
'Doctrine Project' (aka Doctrine) has the ability to create DB migrations for existing DB structures, so you can recreate the existing structure. It can be easily implemented in Symfony, Laravel, also in Yii and many frameworks.
Sample from:
http://symfony.com/legacy/doc/doctrine/1_2/en/07-Migrations
From Database
If you have an existing database you can build a set of migration
classes that will re-create your database by running the following
command.
$ ./symfony doctrine:generate-migrations-db
From Models
If you have an existing set of models you can build a set of migration
classes that will create your database by running the following
command.
$ ./symfony doctrine:generate-migrations-models
Here is a Laravel package I created that does exactly that. It automatically generates clean and accurate Laravel migrations from your existing database.
As it doesn't make any assumptions of the database, it should work on any database structure while even keeping the original index and foreign key names.
https://github.com/Xethron/migrations-generator
Well since migration is about setting up your database structure and make changes to it, not to reflect a current database there is no such way.
And this is also not a step you have to make. You can start from where you are at the moment, which will make you able to rollback up to this point. Which means you can make migrations for your current tables without having to specify their entire structure, but just the changes only.
Let's say you have a table called user and want to add their firstname to it.
php artisan migrate:make add_firstname_to_user
Now go into application/migrations and find the migration file, add this
public function up()
{
Schema::table('user', function($table)
{
$table->string('firstname');
});
}
public function down() {
Schema::table('user', function($table)
{
$table->drop_column('firstname');
});
}
Now you can add migrate it
php artisan migrate:install // if you haven't run this, should only be once
php artisan migrate
.. and rollback using
php artisan migrate:rollback
This will add or drop the column firstname, without affecting your table in any other way.
As for Yii 1.x, schmunk has created a wonderful database-command yiic command.
This command covers only up migrations. You must write your own down migrations.
To use it:
Get the newest version from GitHub and put it's contents into /protected/commands folder (create one, if it does not exist). Note, that you need to put contents as is (without subfolder for this particular command), which is contrary to what we do for example for extensions.
Rename EDatabaseCommand.php file (and class inside) to DatabaseCommand.php, if you want to use yiic database command (as suggested in docs). Without this fix, you'll have to use yiic edatabase command, as there's slight inconsistency between docs and the code (at least in the newest version, as of writing this; maybe schmunk is going to fix this).
Having this, navigate back to protected folder in your console and execute yiic database dump migration_name --prefix=table_name.
This will create a migration protected/runtime/migration_name.php file with proper date and time in the beginning of file name, filled with series of CDbMigration commands to recreate your database schema. Visit "Usage" section in the docs to read more about customizing command.
I think that the answer is: https://github.com/jamband/yii2-schemadump for Yii2
"This command to generate the schema from an existing database."
I use both Yii and Laravel and I could not find what you require for either of them. They both create empty files and you need to create the migration script yourself.
For a table of 150 tables it will be challenge to create the migrations yourself, but it is not quite as hard as you imagine. Because you already have the information on the fields it should not take so long to create.
After doing some research, here's what you're going to need for Laravel: https://github.com/XCMer/larry-four-generator
(version 4 at least, who knows how long this will work, Laravel changes too fast and has too many breaking changes)
You'll want to run php artisan larry:fromdb and it'll show you the tables...You can also exclude or only process certain tables (look at the readme).
Again, super super useful if you like to build your schema in something like MySQL Workbench. I also saw mention of a package that would parse the workbench files...But the link was dead.
You may also wish to use this larry package with: https://github.com/JeffreyWay/Laravel-4-Generators
You can then create scaffolding a la CakePHP style.
Alternatively, try this package: https://github.com/barryvdh/laravel-migration-generator
There is one now for Yii:
This allows a distributed team to easily update the db locally and then distribute it's updates with thee other developers automatically with the rest of the code via a versioning control system (I used git). It also performs a full initial db dump to xml and to a migration file.
project home:
https://code.google.com/p/yii-automatically-generated-migration-files/
source code:
https://code.google.com/p/yii-automatically-generated-migration-files/source/checkout
I've created it from scratch as I was annoyed with the fact that I had to do this manually in order to distribute it to my team.
Hope it helps!
Feel free to share bugs, improvements and comments.
I am building a complex application but i want to know that is it safe to use doctrine migrations in production.
For eg. the site has been used for 1 year and company wants to add extra attribute to user table.
So do i straight way chnage by going in database or through doctrine migrations
This is one of the intended uses (and benefits) of migrations - to automate the changes to your database quickly and accurately. Yes, they can and in most cases should be used to update your database in production.
Edit: The Symfony2 documentation also explains clearly this is one of the purposes of migrations.
Of course, the end goal of writing migrations is to be able to use them to reliably update your database structure when you deploy your application. By running the migrations locally (or on a beta server), you can ensure that the migrations work as you expect.
...
Yes it would be safe.
I would just add an extra attribute in the User entity. Then run the doctrine:generate:entities command. That should generate the get/set methods. Then just update your database using doctrine:schema:update --force. That should add it into your database table.
Question about migrations, announced at one of the latest releases(1.1.6, am I right?)
So, i have a site working with yii 1.1.5 and i want use migrations now, cause site progressing every day. What is the best way to describe first migration, which include all my current database schema?
when you say describe first migration do you mean the class and file name?
yiic migrate create init_db_schema
EDIT
In which case I don't believe the migration tool can reverse engineer an existing db and create the migration for you. So, you'll probably have to manually do it. You could use PHPMyAdmin, MySQL Browser/Workbench to generate the CREATE commands for you and inside your migration script, create the command e.g.
$cmd = $this->getDbConnection()->createCommand($sql);
$cmd->execute();
(Make this CW if needed)
We are two developers working on a web application based (PHP5, ZF, Doctrine, MySQL5). We are working each with a local webserver and a local database. The database schema is defined in a YAML file.
What's the best way to keep our database schemas in sync?
Here's how we do it: Whenever developer "A" makes a change, he generates a migration class. Then he commits the migration file developer "B" executes the migration class.
But creating a migration class on every db change is a rather tedious process.
Do you have a better solution?
I don't know how you do in the Zend Framework with Doctrine. Here's how I would do it in Symfony with Propel. Though the exact procedure may vary, but the underlying concept is the same.
I have unit tests on my DAL.
Whenever the schema changes, we check in the yml and the generated ORM code ( You do have a source control, don't you). I set the check-in to auto-mode, meaning I will get all the check-in instantly.
If the schema changes don't affect my thing, then I would just ignore the changes. But if the schema changes break my thing, then I will rebuild my form, ORM classes and whatnot by using symfony propel build command. Rebuilding those infrastructures is just a single command line thing, so there is no problem for me.
Finally, after rebuilding, I will run my unit tests, to make sure everything is OK. If not, I better get them fixed!
I see that this question is already answered but Doctrine can migrate your databases for you without having to blow away the whole thing. We use this for every schema change where one developer changes his/her local yaml file, generates new models locally, creates a migration using Doctrine, runs that migration locally to change the db, then checks in both the new yaml file and the migration. Then other developers check out the changed yaml file and migration, then they generate new models and run the migration to sync their db. Deploying the code to our QA and production environments is pretty much the same process.
More information on Doctrine migrations can be found on the Doctrine site.