headers = $table['header']; $this->rows = $table['rows']; $this->crossingChar = '+'; $this->horizontalBorderChar = '-'; $this->verticalBorderChar = '|'; $this->borderFormat = '%s'; $this->cellHeaderFormat = '%s'; $this->cellRowFormat = '%s'; $this->paddingChar = ' '; $this->padType = STR_PAD_RIGHT; } /** * Renders table to output. * * Example: * +---------------+-----------------------+------------------+ * | ISBN | Title | Author | * +---------------+-----------------------+------------------+ * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | * +---------------+-----------------------+------------------+ * */ public function render($out = true){ if(!$this->rows) exit('invalid table content'); //获得表头行首 +---------------+-----------------------+------------------+ $output = $this->renderRowSeparator(); //获取头部输出| ISBN | Title | Author | $output .= $this->renderRow($this->headers, $this->cellHeaderFormat); //header存在的话再输出行分割符 if ($this->headers) { $output .= $this->renderRowSeparator(); } //渲染每一行 foreach ($this->rows as $row) { $output .= $this->renderRow($row, $this->cellRowFormat); } if ($this->rows) { $output .= $this->renderRowSeparator(); } if($out){ exit($output); }else{ $this->cleanup(); return $output; } } public function renderWitoutHeadTail($out = true){ if(!$this->rows) exit('invalid table content'); //获取头部输出| ISBN | Title | Author | $output .= $this->renderRow($this->headers, $this->cellHeaderFormat); //header存在的话再输出行分割符 if ($this->headers) { $output .= $this->renderRowSeparator(); } //渲染每一行 foreach ($this->rows as $row) { $output .= $this->renderRow($row, $this->cellRowFormat); } if($out){ print($output); }else{ $this->cleanup(); return $output; } } //渲染表格行起始分割行 private function renderRowSeparator(){ if (0 === $count = $this->getNumberOfColumns()) { return; } $markup = $this->crossingChar; for ($column = 0; $column < $count; $column++) { $markup .= str_repeat($this->horizontalBorderChar, $this->getColumnWidth($column)) .$this->crossingChar ; } return sprintf($this->borderFormat, $markup).PHP_EOL; } /** * 渲染表格行. * * Example: | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | * * @param array $row * @param string $cellFormat */ private function renderRow(array $row, $cellFormat){ if (empty($row)) { return; } $output = $this->renderColumnSeparator(); for ($column = 0, $count = $this->getNumberOfColumns(); $column < $count; $column++) { $output .= $this->renderCell($row, $column, $cellFormat); $output .= $this->renderColumnSeparator(); } $output .= $this->writeln(''); return $output; } /** * 带边距的渲染单元格. * * @param array $row * @param integer $column * @param string $cellFormat */ private function renderCell(array $row, $column, $cellFormat){ $cell = isset($row[$column]) ? $row[$column] : ''; return sprintf( $cellFormat, $this->str_pad( $this->paddingChar.$cell.$this->paddingChar, $this->getColumnWidth($column), $this->paddingChar, $this->padType ) ); } /** * 渲染水平列分隔符. */ private function renderColumnSeparator(){ return(sprintf($this->borderFormat, $this->verticalBorderChar)); } /** * 获取表格的列数. * * @return int */ private function getNumberOfColumns() { if (null !== $this->numberOfColumns) { return $this->numberOfColumns; } $columns = array(0); $columns[] = count($this->headers); foreach ($this->rows as $row) { $columns[] = count($row); } return $this->numberOfColumns = max($columns); } /** * 获取列宽. * * @param integer $column * * @return int */ private function getColumnWidth($column) { if (isset($this->columnWidths[$column])) { return $this->columnWidths[$column]; } $lengths = array(0); $lengths[] = $this->getCellWidth($this->headers, $column); foreach ($this->rows as $row) { $lengths[] = $this->getCellWidth($row, $column); } return $this->columnWidths[$column] = max($lengths) + 2; } /** * 获取单元格宽度. * * @param array $row * @param integer $column * * @return int */ private function getCellWidth(array $row, $column) { if ($column < 0) { return 0; } if (isset($row[$column])) { return $this->strlen($row[$column]); } return $this->getCellWidth($row, $column - 1); } /** * Returns the length of a string, using mb_strlen if it is available. * * @param string $string The string to check its length * * @return integer The length of the string */ protected function strlen($string) { // if (!function_exists('mb_strlen')) { return (strlen($string) + mb_strlen($string,'UTF8')) / 2; // } // if (false === $encoding = mb_detect_encoding($string)) { // return strlen($string); // } // return mb_strlen($string, $encoding); } /** * Called after rendering to cleanup cache data. */ private function cleanup(){ $this->columnWidths = array(); $this->numberOfColumns = null; } public function writeln($line=''){ return $line.PHP_EOL; } public function str_pad($input , $pad_length ,$pad_string , $pad_type){ $strlen = $this->strlen($input); if($strlen < $pad_length){ $difference = $pad_length - $strlen; switch ($pad_type) { case STR_PAD_RIGHT: return $input . str_repeat($pad_string, $difference); break; case STR_PAD_LEFT: return str_repeat($pad_string, $difference) . $input; break; default: $left = $difference / 2; $right = $difference - $left; return str_repeat($pad_string, $left) . $input . str_repeat($pad_string, $right); break; } }else{ return $input; } } //生成当前数据库指定表的数据字典(字符串) public function generate($tableName=''){ $this->crossingChar = '|'; $out_array = array(); $output = ''; if($tableName){ echo substr($tableName, strlen(C('DB_PREFIX'))).PHP_EOL; $rows = array(); $array = M()->query('SHOW FULL COLUMNS FROM '.$tableName); foreach ($array as $key => $value) { $rows[] = array($value['Field'], $value['Type'], $value['Comment']); } $this->headers = array('字段','类型','注释'); $this->rows = $rows; $this->renderWitoutHeadTail(); } echo PHP_EOL; } public function generateAll(){ $tables = M()->query('SHOW TABLE STATUS;'); $tables = array_column($tables,'Name'); foreach ($tables as $value) { $this->generate($value); $this->cleanup(); } } }