Во многих предприятиях, разместивших свои ресурсы в интернете, осталось большое количество
программных комплексов и различных скриптов, работающих с данными в формате dbase.
Появилась задача обратной совместимости.
Данный класс поможет Вам преобразовывать базы данных mysql в dbase.

Для работы этого скрипта необходимо, чтобы php был скомпилирован с поддержкой dbase.
Чтобы узнать это, достаточно вызвать функцию phpinfo(). Если в строке configure command
сведений о версии php есть параметр --enable-dbase, значит Ваша версия поддерживает dbase
(можно также посмотреть в разделе additional modules наличие строки dbase).

HTML
Текст

  1. < ?php

  2. class convdbase
  3. {
  4. var $conv_dir; // каталог конвертации - здесь будут dbf-файлы

  5. var $struct; // структура текущей таблицы,
  6. // используется при конвертации данных

  7. function convdbase($dir)
  8. {
  9. $this->setoutdir($dir);
  10. }

  11. // имя поля и его тип формата mysql преобразуем к dbase
  12. // например: code int(10), преобразуем к array('code', 'n', 10, 0)
  13. // если $mysql == true, то возвращаем только тип int
  14. // который записывается в $this->struct
  15. function getfield($f_name, $f_type, $mysql = false)
  16. {
  17. $len = 0;
  18. $perc = 0;

  19. $pos = strpos($f_type, '(');
  20. if($pos)
  21. {
  22. $type = strtolower(substr($f_type, 0, $pos));
  23. sscanf(substr($f_type, $pos), '(%d,%d)', &#038;$len, &#038;$perc);
  24. }
  25. else
  26. $type = strtolower($f_type);

  27. if($mysql)
  28. return $type;

  29. switch($type)
  30. {
  31. case 'double': case 'float':
  32. $len = 19; $perc = 3;
  33. $type = 'n';
  34. break;
  35. case 'enum':
  36. $len = 5;
  37. case 'int': case 'tinyint': case 'smallint':
  38. if(!$len)
  39. $len = 19;
  40. $perc = 0;
  41. // break не нужен
  42. case 'decimal':
  43. $type = 'n';
  44. break;
  45. case 'tinytext': case 'text': case 'longtext':
  46. case 'varchar': case 'char':
  47. if(!$len || $len > 254)
  48. $len = 254;
  49. $type = 'c';
  50. break;
  51. case 'year': case 'datetime': case 'timestamp':
  52. $len = $perc = 0;
  53. $type = 'd';
  54. break;
  55. }
  56. $field = array($f_name, $type, $len, $perc);
  57. return $field;
  58. }

  59. // установка исходящего каталога
  60. function setoutdir($dir)
  61. {
  62. $this->conv_dir = $dir;
  63. @mkdir($this->conv_dir, 0777);
  64. }

  65. // конвертация данных
  66. function convertdata($row)
  67. {
  68. $data = array();
  69. for($i = 0; $i < sizeof($this->struct); $i++)
  70. {
  71. switch($this->struct[$i])
  72. {
  73. case 'year': case 'datetime': case 'timestamp':
  74. $data[] = substr($row[$i], 0, 8);
  75. break;
  76. case 'tinytext': case 'text': case 'longtext':
  77. case 'varchar': case 'char':
  78. if(strlen($row[$i]) > 254)
  79. {
  80. $data[] = substr($row[$i], 0, 254);
  81. break;
  82. }
  83. // break не нужен
  84. case 'smallint': case 'double': case 'float': case 'enum':
  85. case 'int': case 'tinyint': case 'decimal': case 'int':
  86. $data[] = $row[$i];
  87. break;
  88. }
  89. }
  90. return $data;
  91. }

  92. // конвертируем базу
  93. function convert($server, $user, $password, $db_name)
  94. {
  95. // отключить тайм-аут
  96. if( !get_cfg_var('safe_mode') )
  97. set_time_limit(0);

  98. $link = mysql_connect($server, $user, $password);
  99. if(!$link)
  100. exit('error connect');

  101. mysql_select_db($db_name);
  102. $tables_query = mysql_query('show tables', $link);

  103. $tek_table = 0; // порядковый номер таблицы - если обязательно
  104. // требуется имя файла не более 8 символов
  105. while($tables = mysql_fetch_array($tables_query, mysql_num) )
  106. {
  107. $table = $tables[0];

  108. $field_array = array();
  109. $this->struct = array();

  110. // создаем структуру таблицы
  111. $fields_query = mysql_query('show fields from ' . $table);
  112. $tek_field = 0;
  113. while ($field = mysql_fetch_array($fields_query, mysql_assoc) )
  114. {
  115. $f_name = $field['field'];

  116. // имена полей dbase не должны быть более 10 символов
  117. if(strlen($f_name) > 10)
  118. $f_name = sprintf('%s%03d', substr($f_name, 0, 7), sizeof($field_array) + 1);

  119. $field_array[] = $this->getfield($f_name, $field['type']);
  120. $this->struct[] = $this->getfield($tek_field, $field['type'], true);
  121. }

  122. if(strlen($table) > 8) // см.выше о именах таблиц более 8 символов
  123. $table_name = sprintf('%s%03d', substr($table, 0, 5), $tek_table++);
  124. else
  125. $table_name = $table;

  126. $base = dbase_create( $this->conv_dir . '/' . $table_name . '.dbf', $field_array);
  127. if($base)
  128. {
  129. // таблица создана - перекидываем данные
  130. $rows_query = mysql_query("select * from " . $table);
  131. while($row = mysql_fetch_array($rows_query, mysql_num))
  132. {
  133. $row = $this->convertdata($row);
  134. if($row)
  135. if( !dbase_add_record($base, $row) )
  136. exit('error add record');
  137. }
  138. dbase_close($base);
  139. }
  140. }
  141. mysql_close($link);
  142. }
  143. }
  144. ?>

А теперь рассмотрим пример использования конвертатора.

HTML
Текст

  1. $dir = './convert_' . date('ymdhi'); // здесь будут dbf
  2. $conv = new convdbase($dir);
  3. $conv->convert('localhost', 'user', 'pass', 'base');

Если типы данных year, datetime, timestamp надо передавать в неизменном виде, приведите их к типу dbase "С",
изменив функции getfield и convertdata.



Постоянные ссылки

При копировании ссылка на TeaM RSN обязательна!

URI

Html (ЖЖ)

BB-код (Для форумов)

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.