Skip to content

Instantly share code, notes, and snippets.

@josevh
Created March 20, 2017 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josevh/e44e743914acdd2a964533ad2bd9c581 to your computer and use it in GitHub Desktop.
Save josevh/e44e743914acdd2a964533ad2bd9c581 to your computer and use it in GitHub Desktop.

Simple Migration Management

Modeled after my experience using Laravel's implementation, but much simpler implementation.

Requires

  • Config_Lite initialized with:
    • config.ini with:
      • env entry (development|production)
      • internal section with
        • migration_ver entry >= 0
  • PDO object
<?php
/**
* Migration
*/
abstract class Migration
{
protected $db;
protected $dbName;
public function __construct($db, $dbName)
{
$this->db = $db;
$this->dbName = $dbName;
}
abstract public function up();
abstract public function down();
}
<?php
/**
* Database Management
*/
class MigrationManager
{
public $version;
public $maxMigrationVersion;
protected $db;
protected $config;
protected $configSection;
protected $env;
protected $migrationsLocation;
protected $migrations = array();
/**
* Constructor
* @param PDO $db DB Connection object
* @param Config_Lite $config Configuration Object
* @param string $migrationsLocation Path to migrations folder
*/
public function __construct($db, $config, $migrationsLocation = __DIR__ . '/migrations')
{
$this->db = $db;
$this->config = $config;
$this->env = $config->get(null, 'env');
$this->configSection = ($config->get(null, 'env') == 'development') ? 'db_development' : 'db_production';
$this->migrationsLocation = $migrationsLocation;
$this->version = $this->readMigrationVersion();
$this->getMigrations();
}
/**
* Process migrations not executed
* @return void
*/
public function migrate()
{
foreach ($this->migrations as $migration) {
if ($migration['number'] <= $this->version) {
continue;
}
require_once $this->migrationsLocation . '/' . $migration['filename'];
$m = new $migration['class'](
$this->db, // db object
$this->config->get($this->configSection, 'database') // db name
);
$m->up();
$this->version = $migration['number'];
}
$this->writeMigrationVersion();
}
/**
* Reverse migrations
* @return void
*/
public function reset()
{
// reverse
arsort($this->migrations);
foreach ($this->migrations as $migration) {
$m = new $migration['class'];
$m->down();
$this->version = $migration['number'] - 1;
}
// re-sort
asort($this->migrations);
$this->writeMigrationVersion();
}
/**
* Get migrations defined
* @return void Sets instance variable $migrations
*/
public function getMigrations()
{
$dir = new DirectoryIterator($this->migrationsLocation);
foreach ($dir as $fileinfo) {
if (!$fileinfo->isDot()) {
$parsedData = $this->parseMigrationFilename($fileinfo->getFilename());
if (!empty($parsedData)) {
$this->migrations[$fileinfo->getFilename()] = $parsedData;
}
}
}
asort($this->migrations);
$last = end($this->migrations);
$this->maxMigrationVersion = $last['number'];
}
/**
* Check if database exists
* @return bool
*/
public function databaseExists()
{
$stmt = $this->db->query("
SELECT
COUNT(*)
FROM
INFORMATION_SCHEMA.SCHEMATA
WHERE
SCHEMA_NAME = '" . $this->config->get($this->configSection, 'database') . "'
");
return (bool) $stmt->fetchColumn();
}
/**
* Parse migration filename for number, class name
* @param string $filename Migration filename
* @return array Migration filenames, numbers, class names
*/
private function parseMigrationFilename($filename)
{
$return = array();
$regex = '/^(\d+)_(.*).(php)$/';
preg_match($regex, $filename, $data);
if (!empty($data)) {
$return = array(
'filename' => $filename,
'class' => $data[2],
'number' => (integer) ltrim($data[1], '0'), // remove leading zeros
);
}
return $return;
}
/**
* Read migration version from .env.ini
* @return integer
*/
private function readMigrationVersion()
{
return (integer) $this->config->get('internal', 'migration_ver');
}
/**
* Write migration version to .env.ini
* @return void
*/
private function writeMigrationVersion()
{
$this->config->set('internal', 'migration_ver', $this->version);
$this->config->save();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment