Sql.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // |
  4. // +----------------------------------------------------------------------
  5. // |
  6. // +----------------------------------------------------------------------
  7. // |
  8. // +----------------------------------------------------------------------
  9. // |
  10. // +----------------------------------------------------------------------
  11. // +----------------------------------------------------------------------
  12. // | 读取Sql文件并返回可执行的sql语句
  13. // +----------------------------------------------------------------------
  14. namespace util;
  15. class Sql
  16. {
  17. /**
  18. * 从sql文件获取纯sql语句
  19. * @param string $sql_file sql文件路径
  20. * @param bool $string 如果为真,则只返回一条sql语句,默认以数组形式返回
  21. * @param array $replace 替换前缀,如:['my_' => 'me_'],表示将表前缀"my_"替换成"me_"
  22. * 这种前缀替换方法不一定准确,比如正常内容内有跟前缀相同的字符,也会被替换
  23. * @return array|false|string|string[]
  24. */
  25. public static function getSqlFromFile(string $sql_file = '', bool $string = false, array $replace = []): array|false|string
  26. {
  27. if (!file_exists($sql_file)) {
  28. return false;
  29. }
  30. // 读取sql文件内容
  31. $handle = self::read_file($sql_file);
  32. // 分割语句
  33. return self::parseSql($handle, $string, $replace);
  34. }
  35. /**
  36. * 分割sql语句
  37. * @param string $content sql内容
  38. * @param bool $string 如果为真,则只返回一条sql语句,默认以数组形式返回
  39. * @param array $replace 替换前缀,如:['my_' => 'me_'],表示将表前缀my_替换成me_
  40. * @return array|string|string[] 除去注释之后的sql语句数组或一条语句
  41. */
  42. public static function parseSql(string $content = '', bool $string = false, array $replace = []): array|string
  43. {
  44. // 被替换的前缀
  45. $from = '';
  46. // 要替换的前缀
  47. $to = '';
  48. // 替换表前缀
  49. if (!empty($replace)) {
  50. $to = current($replace);
  51. $from = current(array_flip($replace));
  52. }
  53. if ($content != '') {
  54. // 纯sql内容
  55. $pure_sql = [];
  56. // 多行注释标记
  57. $comment = false;
  58. // 按行分割,兼容多个平台
  59. $content = str_replace(["\r\n", "\r"], "\n", $content);
  60. $content = explode("\n", trim($content));
  61. // 循环处理每一行
  62. foreach ($content as $key => $line) {
  63. // 跳过空行
  64. if ($line == '') {
  65. continue;
  66. }
  67. // 跳过以#或者--开头的单行注释
  68. if (preg_match("/^(#|--)/", $line)) {
  69. continue;
  70. }
  71. // 跳过以/**/包裹起来的单行注释
  72. if (preg_match("/^\/\*(.*?)\*\//", $line)) {
  73. continue;
  74. }
  75. // 多行注释开始
  76. if (str_starts_with($line, '/*')) {
  77. $comment = true;
  78. continue;
  79. }
  80. // 多行注释结束
  81. if (str_ends_with($line, '*/')) {
  82. $comment = false;
  83. continue;
  84. }
  85. // 多行注释没有结束,继续跳过
  86. if ($comment) {
  87. continue;
  88. }
  89. // 替换表前缀
  90. if ($from != '') {
  91. $line = str_replace('`' . $from, '`' . $to, $line);
  92. }
  93. // sql语句
  94. array_push($pure_sql, $line);
  95. }
  96. // 只返回一条语句
  97. if ($string) {
  98. return implode("", $pure_sql);
  99. }
  100. // 以数组形式返回sql语句
  101. $pure_sql = implode("\n", $pure_sql);
  102. $pure_sql = explode(";\n", $pure_sql);
  103. return $pure_sql;
  104. } else {
  105. return $string ? '' : [];
  106. }
  107. }
  108. /**
  109. * 读取文件内容
  110. * @param string $filename 文件名
  111. * @return false|string
  112. */
  113. public static function read_file(string $filename): false|string
  114. {
  115. $content = '';
  116. if (function_exists('file_get_contents')) {
  117. @$content = file_get_contents($filename);
  118. } else {
  119. if (@$fp = fopen($filename, 'r')) {
  120. @$content = fread($fp, filesize($filename));
  121. @fclose($fp);
  122. }
  123. }
  124. return $content;
  125. }
  126. }