Welcome Guest, Not a member yet? Register   Sign In
CI Migration Library and dynamic config values
#2

(This post was last modified: 04-02-2016, 06:51 AM by josepostiga. Edit Reason: Typo )

Just for future reference, I've managed to handle this situations by extending the core Migration Library and making a few changes regarding the configuration getters and setters. The final class goes like this:

PHP Code:
<?php

defined
('BASEPATH') or exit('No direct script access allowed');

class 
MY_Migration extends CI_Migration
{
    
/**
     * Initialize Migration Class
     *
     * @param    array    $config
     * @return    void
     */
    
public function __construct($config = array())
    {
        
// Only run this constructor on main library load
        
if ( ! in_array(get_class($this), array('CI_Migration'config_item('subclass_prefix').'Migration'), TRUE))
        {
            return;
        }

        
// sets initial configuration
        
$this->setConfig($config);

        
log_message('info''Migrations Class Initialized');

        
// Are they trying to use migrations while it is disabled?
        
if ($this->_migration_enabled !== TRUE)
        {
            
show_error('Migrations has been loaded but is disabled or set up incorrectly.');
        }

        
// If not set, set it
        
$this->_migration_path !== '' OR $this->_migration_path APPPATH.'migrations/';

        
// Add trailing slash if not set
        
$this->_migration_path rtrim($this->_migration_path'/').'/';

        
// Load migration language
        
$this->lang->load('migration');

        
// They'll probably be using dbforge
        
$this->load->dbforge();

        
// Make sure the migration table name was set.
        
if (empty($this->_migration_table))
        {
            
show_error('Migrations configuration file (migration.php) must have "migration_table" set.');
        }

        
// Migration basename regex
        
$this->_migration_regex = ($this->_migration_type === 'timestamp')
            ? 
'/^\d{14}_(\w+)$/'
            
'/^\d{3}_(\w+)$/';

        
// Make sure a valid migration numbering type was set.
        
if ( ! in_array($this->_migration_type, array('sequential''timestamp')))
        {
            
show_error('An invalid migration numbering type was specified: '.$this->_migration_type);
        }

        
// Do we auto migrate to the latest migration?
        
if ($this->_migration_auto_latest === TRUE && ! $this->latest())
        {
            
show_error($this->error_string());
        }
    }

    
/**
     * Sets library configuration vars.
     *
     * @param array $config
     * @return void
     */
    
public function setConfig($config = array())
    {
        
// loads configuration file
        
$this->config->load('migration');

        
// checks configuration to override
        
if (count($config) > 0) {
            foreach (
$config as $key => $val) {
                
$this->{'_'.$key} = $val;
            }
        }
    }

    
/**
     * Checks if required migrations table exists. Creates if not.
     *
     * @return void
     */
    
protected function checkMigrationsTable()
    {
        if ( ! 
$this->db->table_exists($this->_migration_table))
        {
            
$this->dbforge->add_field(array(
                
'version' => array('type' => 'BIGINT''constraint' => 20),
            ));

            
$this->dbforge->create_table($this->_migration_tableTRUE);

            
$this->db->insert($this->_migration_table, array('version' => 0));
        }
    }

    
/**
     * Migrate to a schema version
     *
     * Calls each migration step required to get to the schema version of
     * choice
     *
     * @param    string    $target_version    Target schema version
     * @return    mixed    TRUE if no migrations are found, current version string on success, FALSE on failure
     */
    
public function version($target_version)
    {
        
// checks migrations table
        
$this->checkMigrationsTable();

        
// Note: We use strings, so that timestamp versions work on 32-bit systems
        
$current_version $this->_get_version();

        if (
$this->_migration_type === 'sequential')
        {
            
$target_version sprintf('%03d'$target_version);
        }
        else
        {
            
$target_version = (string) $target_version;
        }

        
$migrations $this->find_migrations();

        if (
$target_version && ! isset($migrations[$target_version]))
        {
            
$this->_error_string sprintf($this->lang->line('migration_not_found'), $target_version);
            return 
FALSE;
        }

        if (
$target_version $current_version)
        {
            
$method 'up';
        }
        elseif (
$target_version $current_version)
        {
            
$method 'down';
            
// We need this so that migrations are applied in reverse order
            
krsort($migrations);
        }
        else
        {
            
// Well, there's nothing to migrate then ...
            
return TRUE;
        }

        
// Validate all available migrations within our target range.
        //
        // Unfortunately, we'll have to use another loop to run them
        // in order to avoid leaving the procedure in a broken state.
        //
        // See https://github.com/bcit-ci/CodeIgniter/issues/4539
        
$pending = array();
        foreach (
$migrations as $number => $file)
        {
            
// Ignore versions out of our range.
            //
            // Because we've previously sorted the $migrations array depending on the direction,
            // we can safely break the loop once we reach $target_version ...
            
if ($method === 'up')
            {
                if (
$number <= $current_version)
                {
                    continue;
                }
                elseif (
$number $target_version)
                {
                    break;
                }
            }
            else
            {
                if (
$number $current_version)
                {
                    continue;
                }
                elseif (
$number <= $target_version)
                {
                    break;
                }
            }

            
// Check for sequence gaps
            
if ($this->_migration_type === 'sequential')
            {
                if (isset(
$previous) && abs($number $previous) > 1)
                {
                    
$this->_error_string sprintf($this->lang->line('migration_sequence_gap'), $number);
                    return 
FALSE;
                }

                
$previous $number;
            }

            include_once(
$file);
            
$class 'Migration_'.ucfirst(strtolower($this->_get_migration_name(basename($file'.php'))));

            
// Validate the migration file structure
            
if ( ! class_exists($classFALSE))
            {
                
$this->_error_string sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
                return 
FALSE;
            }
            
// method_exists() returns true for non-public methods,
            // while is_callable() can't be used without instantiating.
            // Only get_class_methods() satisfies both conditions.
            
elseif ( ! in_array($methodarray_map('strtolower'get_class_methods($class))))
            {
                
$this->_error_string sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);
                return 
FALSE;
            }

            
$pending[$number] = array($class$method);
        }

        
// Now just run the necessary migrations
        
foreach ($pending as $number => $migration)
        {
            
log_message('debug''Migrating '.$method.' from version '.$current_version.' to version '.$number);

            
$migration[0] = new $migration[0];
            
call_user_func($migration);
            
$current_version $number;
            
$this->_update_version($current_version);
        }

        
// This is necessary when moving down, since the the last migration applied
        // will be the down() method for the next migration up from the target
        
if ($current_version <> $target_version)
        {
            
$current_version $target_version;
            
$this->_update_version($current_version);
        }

        
log_message('debug''Finished migrating to '.$current_version);
        return 
$current_version;
    }

Best regards,
José Postiga
Senior Backend Developer
Reply


Messages In This Thread
RE: CI Migration Library and dynamic config values - by josepostiga - 04-02-2016, 06:49 AM



Theme © iAndrew 2016 - Forum software by © MyBB