DataDictionary.class.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <?php
  2. namespace OT;
  3. class DataDictionary{
  4. public function __construct($table){
  5. $this->headers = $table['header'];
  6. $this->rows = $table['rows'];
  7. $this->crossingChar = '+';
  8. $this->horizontalBorderChar = '-';
  9. $this->verticalBorderChar = '|';
  10. $this->borderFormat = '%s';
  11. $this->cellHeaderFormat = '%s';
  12. $this->cellRowFormat = '%s';
  13. $this->paddingChar = ' ';
  14. $this->padType = STR_PAD_RIGHT;
  15. }
  16. /**
  17. * Renders table to output.
  18. *
  19. * Example:
  20. * +---------------+-----------------------+------------------+
  21. * | ISBN | Title | Author |
  22. * +---------------+-----------------------+------------------+
  23. * | 99921-58-10-7 | Divine Comedy | Dante Alighieri |
  24. * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
  25. * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
  26. * +---------------+-----------------------+------------------+
  27. *
  28. */
  29. public function render($out = true){
  30. if(!$this->rows)
  31. exit('invalid table content');
  32. //获得表头行首 +---------------+-----------------------+------------------+
  33. $output = $this->renderRowSeparator();
  34. //获取头部输出| ISBN | Title | Author |
  35. $output .= $this->renderRow($this->headers, $this->cellHeaderFormat);
  36. //header存在的话再输出行分割符
  37. if ($this->headers) {
  38. $output .= $this->renderRowSeparator();
  39. }
  40. //渲染每一行
  41. foreach ($this->rows as $row) {
  42. $output .= $this->renderRow($row, $this->cellRowFormat);
  43. }
  44. if ($this->rows) {
  45. $output .= $this->renderRowSeparator();
  46. }
  47. if($out){
  48. exit($output);
  49. }else{
  50. $this->cleanup();
  51. return $output;
  52. }
  53. }
  54. public function renderWitoutHeadTail($out = true){
  55. if(!$this->rows)
  56. exit('invalid table content');
  57. //获取头部输出| ISBN | Title | Author |
  58. $output .= $this->renderRow($this->headers, $this->cellHeaderFormat);
  59. //header存在的话再输出行分割符
  60. if ($this->headers) {
  61. $output .= $this->renderRowSeparator();
  62. }
  63. //渲染每一行
  64. foreach ($this->rows as $row) {
  65. $output .= $this->renderRow($row, $this->cellRowFormat);
  66. }
  67. if($out){
  68. print($output);
  69. }else{
  70. $this->cleanup();
  71. return $output;
  72. }
  73. }
  74. //渲染表格行起始分割行
  75. private function renderRowSeparator(){
  76. if (0 === $count = $this->getNumberOfColumns()) {
  77. return;
  78. }
  79. $markup = $this->crossingChar;
  80. for ($column = 0; $column < $count; $column++) {
  81. $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column))
  82. .$this->crossingChar
  83. ;
  84. }
  85. return sprintf($this->borderFormat, $markup).PHP_EOL;
  86. }
  87. /**
  88. * 渲染表格行.
  89. *
  90. * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens |
  91. *
  92. * @param array $row
  93. * @param string $cellFormat
  94. */
  95. private function renderRow(array $row, $cellFormat){
  96. if (empty($row)) {
  97. return;
  98. }
  99. $output = $this->renderColumnSeparator();
  100. for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) {
  101. $output .= $this->renderCell($row, $column, $cellFormat);
  102. $output .= $this->renderColumnSeparator();
  103. }
  104. $output .= $this->writeln('');
  105. return $output;
  106. }
  107. /**
  108. * 带边距的渲染单元格.
  109. *
  110. * @param array $row
  111. * @param integer $column
  112. * @param string $cellFormat
  113. */
  114. private function renderCell(array $row, $column, $cellFormat){
  115. $cell = isset($row[$column]) ? $row[$column] : '';
  116. return sprintf(
  117. $cellFormat,
  118. $this->str_pad(
  119. $this->paddingChar.$cell.$this->paddingChar,
  120. $this->getColumnWidth($column),
  121. $this->paddingChar,
  122. $this->padType
  123. )
  124. );
  125. }
  126. /**
  127. * 渲染水平列分隔符.
  128. */
  129. private function renderColumnSeparator(){
  130. return(sprintf($this->borderFormat, $this->verticalBorderChar));
  131. }
  132. /**
  133. * 获取表格的列数.
  134. *
  135. * @return int
  136. */
  137. private function getNumberOfColumns() {
  138. if (null !== $this->numberOfColumns) {
  139. return $this->numberOfColumns;
  140. }
  141. $columns = array(0);
  142. $columns[] = count($this->headers);
  143. foreach ($this->rows as $row) {
  144. $columns[] = count($row);
  145. }
  146. return $this->numberOfColumns = max($columns);
  147. }
  148. /**
  149. * 获取列宽.
  150. *
  151. * @param integer $column
  152. *
  153. * @return int
  154. */
  155. private function getColumnWidth($column) {
  156. if (isset($this->columnWidths[$column])) {
  157. return $this->columnWidths[$column];
  158. }
  159. $lengths = array(0);
  160. $lengths[] = $this->getCellWidth($this->headers, $column);
  161. foreach ($this->rows as $row) {
  162. $lengths[] = $this->getCellWidth($row, $column);
  163. }
  164. return $this->columnWidths[$column] = max($lengths) + 2;
  165. }
  166. /**
  167. * 获取单元格宽度.
  168. *
  169. * @param array $row
  170. * @param integer $column
  171. *
  172. * @return int
  173. */
  174. private function getCellWidth(array $row, $column) {
  175. if ($column < 0) {
  176. return 0;
  177. }
  178. if (isset($row[$column])) {
  179. return $this->strlen($row[$column]);
  180. }
  181. return $this->getCellWidth($row, $column - 1);
  182. }
  183. /**
  184. * Returns the length of a string, using mb_strlen if it is available.
  185. *
  186. * @param string $string The string to check its length
  187. *
  188. * @return integer The length of the string
  189. */
  190. protected function strlen($string) {
  191. // if (!function_exists('mb_strlen')) {
  192. return (strlen($string) + mb_strlen($string,'UTF8')) / 2;
  193. // }
  194. // if (false === $encoding = mb_detect_encoding($string)) {
  195. // return strlen($string);
  196. // }
  197. // return mb_strlen($string, $encoding);
  198. }
  199. /**
  200. * Called after rendering to cleanup cache data.
  201. */
  202. private function cleanup(){
  203. $this->columnWidths = array();
  204. $this->numberOfColumns = null;
  205. }
  206. public function writeln($line=''){
  207. return $line.PHP_EOL;
  208. }
  209. public function str_pad($input , $pad_length ,$pad_string , $pad_type){
  210. $strlen = $this->strlen($input);
  211. if($strlen < $pad_length){
  212. $difference = $pad_length - $strlen;
  213. switch ($pad_type) {
  214. case STR_PAD_RIGHT:
  215. return $input . str_repeat($pad_string, $difference);
  216. break;
  217. case STR_PAD_LEFT:
  218. return str_repeat($pad_string, $difference) . $input;
  219. break;
  220. default:
  221. $left = $difference / 2;
  222. $right = $difference - $left;
  223. return str_repeat($pad_string, $left) . $input . str_repeat($pad_string, $right);
  224. break;
  225. }
  226. }else{
  227. return $input;
  228. }
  229. }
  230. //生成当前数据库指定表的数据字典(字符串)
  231. public function generate($tableName=''){
  232. $this->crossingChar = '|';
  233. $out_array = array();
  234. $output = '';
  235. if($tableName){
  236. echo substr($tableName, strlen(C('DB_PREFIX'))).PHP_EOL;
  237. $rows = array();
  238. $array = M()->query('SHOW FULL COLUMNS FROM '.$tableName);
  239. foreach ($array as $key => $value) {
  240. $rows[] = array($value['Field'], $value['Type'], $value['Comment']);
  241. }
  242. $this->headers = array('字段','类型','注释');
  243. $this->rows = $rows;
  244. $this->renderWitoutHeadTail();
  245. }
  246. echo PHP_EOL;
  247. }
  248. public function generateAll(){
  249. $tables = M()->query('SHOW TABLE STATUS;');
  250. $tables = array_column($tables,'Name');
  251. foreach ($tables as $value) {
  252. $this->generate($value);
  253. $this->cleanup();
  254. }
  255. }
  256. }