Database Migration - Library Overview and Usage

    As you can read , a new version of CodeIgniter has recently been released, one of the innovations of which is the Migration library . One of its main developers, Phil Sturgeon, was so inspired by the convenience of managing database versions for Rails that he decided to create an analog of such a method for CodeIgniter, and now, in the end, you can see this library in the official distribution.
    From this article you will get a general idea of ​​migrations, and also learn how to create them. In the second part , we will see how easily they can be integrated into your application.
    This article will be useful for novice CodeIgniter users, but I hope that more advanced colleagues will learn about this wonderful library and learn something new for themselves.

    Among other things, this library is not at all complicated, and implementing it if desired for any other platform will not be difficult!


    Library Overview


    The Migration library allows us to store all database changes in the application, and roll them or roll them back if necessary. This can be convenient for development in a team - you don’t need to explain to your colleague what needs to be changed in the database so that your code works, and when uploading new versions of the site to the battle server. Or, at worst, you can always quickly roll back to the old version if you messed up somewhere.

    To understand in general terms how the library works, consider the following primitive scenario:
    0. Suppose we have 0 version of the application with an initial database (also version 0) .
    1.During development, we understand that in order to implement new functionality (for example, a newsletter subscription system), we will need to make changes not only in the application code, but also in the database structure.
    2. To do this, we will specify in the config that the database version for this version of the code will be 1 and together with the new code we will create the 001 migration , specifying actions for it both for the upgrade and for the database downgrade (in case you need to roll back the application version )
    3. Then we implement some kind of update rolling mechanism - this can be a page in the admin panel, a solution using the CLI, or even a fully automatic update when downloading from the version control system.
    4.We upload the new project code to the site, start the migration to the desired version, and voila!

    Now imagine that you need to update the application through 3 versions in advance, or on the test server to see how the version made a couple of months ago was implemented? Easy, just by changing the code, migrate to the desired version of the database (migration will occur gradually, for example, from the 4th to the 1st, the 3rd and 2nd will roll first, and then the 1st version)!

    Are you inspired by such an opportunity as I want to try? Nothing is easier!

    Practical use


    As a matter of fact, the library is completely easy to use, and for its implementation in the project you need to add \ correct quite a few lines of code.
    The whole process of creating migrations will not take a dozen minutes of time, but will save you and your colleagues working on the same project decently.

    Create the class MY_Migration

    So, for starters, we will need to file a little bit to expand the Migration class .
    What for? Everything is very simple, by default this class is not able to report which versions of the database and code are current, and it is not entirely correct to implement these checks throughout the code, it is better to do this in one place.
    To do this, we will use the standard class extension methodology used in CodeIgniter - create the file % site_path% / application / libraries / MY_Migration.php with a couple of dozen lines of code inside.
    This class will add 2 more public methods to the implementation of the ancestor:
    	/**
    	 * Wrapper function for the protected _get_version.
    	 * Get's the database current version
    	 *
    	 * @access	public
    	 * @return	integer	Current DB Migration version
    	 */
    	public function get_db_version() {	
    		return parent::_get_version();
    	}
    	/**
    	 * Retrieves current file system version
    	 *
    	 * @access	public
    	 * @return	integer	Current file system Migration version
    	 */
    	public function get_fs_version() {
    		return $this->_migration_version;
    	}
    

    Note: hereinafter, abbreviated code listings, a link to all the files used in the tutorial at the end of the article can be shown .

    As you can see, functions are just wrappers for the protected method for obtaining the database version and again the $ _migration_version properties are protected , and they demonstrate quite clearly the use of encapsulation . I also advise you to pay attention to an important point: in the original Migration class there is a limitation, due to which its constructor is executed only when the parent class is initialized. Therefore, for the application to work correctly, automatically initializing MY_Migration

    instead of the original, you need to duplicate the constructor of the parent class, changing the condition on line 41 in it:
    	public function __construct($config = array()) { 
    		# Only run this constructor on main library load
    		if (get_parent_class($this) !== FALSE)
    		{  
    			return;
    		}
    	###	   Other code here...
    	}
    

    on the
    	public function __construct($config = array()) { 
    		# Only run this constructor on main library load
    		if (get_parent_class($this) !== FALSE && get_class($this)!='MY_Migration')
    		{  
    			return;
    		}
    	###	  Other code here...
    	}
    


    Create a migration

    By expanding the base class, the matter remains small. In order for the library to be able to roll or roll back changes to the database, it is necessary to create a migration file containing the Migration descendant class (in our case MY_Migration ).
    Since this is our first migration, we will create the following file: % site_path% / application / migrations / 001_add_messages.php containing the up and down functions:

    db->query("
    			CREATE TABLE IF NOT EXISTS `email_list` (
    				`list_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    				`email` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
    			) ENGINE=MyISAM;");
    	}
    	public function down() {
    		$this->db->query("DROP TABLE IF EXISTS `email_list`");
    	}
    }
    

    Please note that the files with migrations contain at the beginning of the 3-tasking digital serial number of the version to which they translate the database, and the class contained in them is called the file name, where instead of the version number is Migration_ .

    Edit config

    Finally, to work with migrations, you need to tweak the config in the % site_path% / application / config / migration.php file a bit and enable them, see if the path and version of the database required for our code to work correctly are specified (standard comments are cut from listing):
    	$config['migration_enabled'] = TRUE;
    	$config['migration_version'] = 1;
    	$config['migration_path'] = APPPATH . 'migrations/';
    

    Please note that I indicated the 1st version, which implies that we have already done the mailing list functionality.


    Total


    Thus, we slightly improved the usability of the library, expanding its functionality, bypassed the pitfall associated with checking the constructor for inheritance of the original class, and also learned how to create migrations.
    As you can see, there is nothing complicated in creating migrations, and, again, they can save you a significant amount of time. Moreover, their implementation in the current project should also not cause any difficulties. By the way, just the introduction will be devoted to my second article, which will appear in the very near future.

    Download the archive with full sources.

    Second part: Database migrations - integration with your application

    PS: There is not enough karma to publish on the CodeIgniter blog, so for now I am publishing the general php blog
    UPD: Good anonymous poured a little karma, transferred to the CodeIgniter blog

    Also popular now: