UPDATE: Эта статья несколько устарела. То что описано в ней является поделкой, которая была изготовлена на коленке ввиду острой необходимости в инструменте миграции БД в рамках одного проекта. Сегодня я готов представить сообществу более удобную разработку: MMP — Инструмент для миграции схемы MySQL в PHP проектах

Понадобился инструментик для миграций структуры таблиц БД. Есть недопиленная тулза в limb-project, но она не допилена, а допиливать ее времени не было.

В итоге родился небольшой скрипт.

В базе в табице db_version хранится текущая версия схемы БД.

Скрипты в папке sql/ создаются этой же тулзой и имеют timestamp в префиксе.

./sql.php create migration_name

Эта комманда в консоли создаст файл типа sql/23498792_migration_name.sql. Остается только в ручную прописать туда запросы, а затем произвести миграцию базы. При таком подходе изменять базу напрямую нельзя, что является огромным минусом такого решения.

При загрузке скрипт будет грузить только те миграции, у которых версия(timestamp) больше, чем максимальная в db_version

Загрузка производится очень просто

bash
  1.  
  2. ./sql.php load
  3.  

А можно просто посмотреть запросы, которые пойдут в базу:

bash
  1.  
  2. ./sql.php load dry
  3.  
php
  1.  
  2. #!/usr/bin/env php
  3. <?php
  4. if('cli'!=php_sapi_name()) exit ;
  5. /* Инициализация DB от приложения - замените на свою */
  6. require_once dirname(__FILE__).'/libs/class.config.php';
  7. require_once dirname(__FILE__).'/autoload.php';
  8.  
  9. Config::getInstance();
  10. spl_autoload_register(array('Autoload','loadClass'));
  11.  
  12. Db::init();
  13. Config::getInstance()->parseDB();
  14.  
  15. mysql_select_db(Config::getInstance()->db_base);
  16.  
  17. /*************************************************************************/
  18.  
  19.  
  20. $tables = mysql_query('show tables');
  21.  
  22. $has_version_table=false;
  23.  
  24. while($table = mysql_fetch_array($tables,MYSQL_NUM))
  25. {
  26. if($table[0] == 'db_version')
  27. {
  28. $has_version_table = true;
  29. break;
  30. }
  31. }
  32.  
  33. if(!$has_version_table)
  34. {
  35. mysql_query('create table db_version (db_version int unsigned not null)');
  36. mysql_query('insert into db_version set db_version = 0');
  37. }
  38.  
  39. if($argc<2){
  40. echo "./sql.php load [dry]\nOR\nsql.php create this_is_the_name_of_migration\n";
  41. }
  42.  
  43. if($argv[1]==='load')
  44. {
  45. $res = mysql_query('select max(db_version) as v from db_version');
  46. $vobj = mysql_fetch_object($res);
  47. $version = intval($vobj->v);
  48.  
  49.  
  50. $files = glob(dirname(__FILE__).'/sql/*.sql');
  51.  
  52. foreach($files as $file){
  53. if(!preg_match('#^.*/sql/(\d+)[^/]*\.sql$#is',$file,$matches)) continue;
  54. $v = intval($matches[1]);
  55. if($v>$version){
  56. $queries = file($file);
  57. echo "Loading file: $file\n";
  58. foreach($queries as $query)
  59. {
  60. if(!strlen(trim($query))) continue;
  61. echo $query,"\n";
  62. if(isset($argv[2]) && $argv[2] === 'dry') continue;
  63. mysql_query($query);
  64. }
  65. if(isset($argv[2]) && $argv[2] === 'dry') continue;
  66. mysql_query('insert into db_version set db_version='.$v);
  67. }
  68. }
  69.  
  70. }elseif($argv[1] === 'create'){
  71. touch(dirname(__FILE__).'/sql/'.time().'_'.str_replace(' ','_',$argv[2]).'.sql');
  72. echo dirname(__FILE__).'/sql/'.time().'_'.str_replace(' ','_',$argv[2]).'.sql',"\n";
  73. }
  74.  
  75.  

Комменты

Добавить коммент