Table.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: yunwuxin <448901948@qq.com>
  10. // +----------------------------------------------------------------------
  11. namespace think\console;
  12. class Table
  13. {
  14. const ALIGN_LEFT = 1;
  15. const ALIGN_RIGHT = 0;
  16. const ALIGN_CENTER = 2;
  17. /**
  18. * 头信息数据
  19. * @var array
  20. */
  21. protected $header = [];
  22. /**
  23. * 头部对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
  24. * @var int
  25. */
  26. protected $headerAlign = 1;
  27. /**
  28. * 表格数据(二维数组)
  29. * @var array
  30. */
  31. protected $rows = [];
  32. /**
  33. * 单元格对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
  34. * @var int
  35. */
  36. protected $cellAlign = 1;
  37. /**
  38. * 单元格宽度信息
  39. * @var array
  40. */
  41. protected $colWidth = [];
  42. /**
  43. * 表格输出样式
  44. * @var string
  45. */
  46. protected $style = 'default';
  47. /**
  48. * 表格样式定义
  49. * @var array
  50. */
  51. protected $format = [
  52. 'compact' => [],
  53. 'default' => [
  54. 'top' => ['+', '-', '+', '+'],
  55. 'cell' => ['|', ' ', '|', '|'],
  56. 'middle' => ['+', '-', '+', '+'],
  57. 'bottom' => ['+', '-', '+', '+'],
  58. 'cross-top' => ['+', '-', '-', '+'],
  59. 'cross-bottom' => ['+', '-', '-', '+'],
  60. ],
  61. 'markdown' => [
  62. 'top' => [' ', ' ', ' ', ' '],
  63. 'cell' => ['|', ' ', '|', '|'],
  64. 'middle' => ['|', '-', '|', '|'],
  65. 'bottom' => [' ', ' ', ' ', ' '],
  66. 'cross-top' => ['|', ' ', ' ', '|'],
  67. 'cross-bottom' => ['|', ' ', ' ', '|'],
  68. ],
  69. 'borderless' => [
  70. 'top' => ['=', '=', ' ', '='],
  71. 'cell' => [' ', ' ', ' ', ' '],
  72. 'middle' => ['=', '=', ' ', '='],
  73. 'bottom' => ['=', '=', ' ', '='],
  74. 'cross-top' => ['=', '=', ' ', '='],
  75. 'cross-bottom' => ['=', '=', ' ', '='],
  76. ],
  77. 'box' => [
  78. 'top' => ['┌', '─', '┬', '┐'],
  79. 'cell' => ['│', ' ', '│', '│'],
  80. 'middle' => ['├', '─', '┼', '┤'],
  81. 'bottom' => ['└', '─', '┴', '┘'],
  82. 'cross-top' => ['├', '─', '┴', '┤'],
  83. 'cross-bottom' => ['├', '─', '┬', '┤'],
  84. ],
  85. 'box-double' => [
  86. 'top' => ['╔', '═', '╤', '╗'],
  87. 'cell' => ['║', ' ', '│', '║'],
  88. 'middle' => ['╠', '─', '╪', '╣'],
  89. 'bottom' => ['╚', '═', '╧', '╝'],
  90. 'cross-top' => ['╠', '═', '╧', '╣'],
  91. 'cross-bottom' => ['╠', '═', '╤', '╣'],
  92. ],
  93. ];
  94. /**
  95. * 设置表格头信息 以及对齐方式
  96. * @access public
  97. * @param array $header 要输出的Header信息
  98. * @param int $align 对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
  99. * @return void
  100. */
  101. public function setHeader(array $header, $align = self::ALIGN_LEFT)
  102. {
  103. $this->header = $header;
  104. $this->headerAlign = $align;
  105. $this->checkColWidth($header);
  106. }
  107. /**
  108. * 设置输出表格数据 及对齐方式
  109. * @access public
  110. * @param array $rows 要输出的表格数据(二维数组)
  111. * @param int $align 对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
  112. * @return void
  113. */
  114. public function setRows(array $rows, $align = self::ALIGN_LEFT)
  115. {
  116. $this->rows = $rows;
  117. $this->cellAlign = $align;
  118. foreach ($rows as $row) {
  119. $this->checkColWidth($row);
  120. }
  121. }
  122. /**
  123. * 检查列数据的显示宽度
  124. * @access public
  125. * @param mixed $row 行数据
  126. * @return void
  127. */
  128. protected function checkColWidth($row)
  129. {
  130. if (is_array($row)) {
  131. foreach ($row as $key => $cell) {
  132. if (!isset($this->colWidth[$key]) || strlen($cell) > $this->colWidth[$key]) {
  133. $this->colWidth[$key] = strlen($cell);
  134. }
  135. }
  136. }
  137. }
  138. /**
  139. * 增加一行表格数据
  140. * @access public
  141. * @param mixed $row 行数据
  142. * @param bool $first 是否在开头插入
  143. * @return void
  144. */
  145. public function addRow($row, $first = false)
  146. {
  147. if ($first) {
  148. array_unshift($this->rows, $row);
  149. } else {
  150. $this->rows[] = $row;
  151. }
  152. $this->checkColWidth($row);
  153. }
  154. /**
  155. * 设置输出表格的样式
  156. * @access public
  157. * @param string $style 样式名
  158. * @return void
  159. */
  160. public function setStyle($style)
  161. {
  162. $this->style = isset($this->format[$style]) ? $style : 'default';
  163. }
  164. /**
  165. * 输出分隔行
  166. * @access public
  167. * @param string $pos 位置
  168. * @return string
  169. */
  170. protected function renderSeparator($pos)
  171. {
  172. $style = $this->getStyle($pos);
  173. $array = [];
  174. foreach ($this->colWidth as $width) {
  175. $array[] = str_repeat($style[1], $width + 2);
  176. }
  177. return $style[0] . implode($style[2], $array) . $style[3] . PHP_EOL;
  178. }
  179. /**
  180. * 输出表格头部
  181. * @access public
  182. * @return string
  183. */
  184. protected function renderHeader()
  185. {
  186. $style = $this->getStyle('cell');
  187. $content = $this->renderSeparator('top');
  188. foreach ($this->header as $key => $header) {
  189. $array[] = ' ' . str_pad($header, $this->colWidth[$key], $style[1], $this->headerAlign);
  190. }
  191. if (!empty($array)) {
  192. $content .= $style[0] . implode(' ' . $style[2], $array) . ' ' . $style[3] . PHP_EOL;
  193. if ($this->rows) {
  194. $content .= $this->renderSeparator('middle');
  195. }
  196. }
  197. return $content;
  198. }
  199. protected function getStyle($style)
  200. {
  201. if ($this->format[$this->style]) {
  202. $style = $this->format[$this->style][$style];
  203. } else {
  204. $style = [' ', ' ', ' ', ' '];
  205. }
  206. return $style;
  207. }
  208. /**
  209. * 输出表格
  210. * @access public
  211. * @param array $dataList 表格数据
  212. * @return string
  213. */
  214. public function render($dataList = [])
  215. {
  216. if ($dataList) {
  217. $this->setRows($dataList);
  218. }
  219. // 输出头部
  220. $content = $this->renderHeader();
  221. $style = $this->getStyle('cell');
  222. if ($this->rows) {
  223. foreach ($this->rows as $row) {
  224. if (is_string($row) && '-' === $row) {
  225. $content .= $this->renderSeparator('middle');
  226. } elseif (is_scalar($row)) {
  227. $content .= $this->renderSeparator('cross-top');
  228. $array = str_pad($row, 3 * (count($this->colWidth) - 1) + array_reduce($this->colWidth, function ($a, $b) {
  229. return $a + $b;
  230. }));
  231. $content .= $style[0] . ' ' . $array . ' ' . $style[3] . PHP_EOL;
  232. $content .= $this->renderSeparator('cross-bottom');
  233. } else {
  234. $array = [];
  235. foreach ($row as $key => $val) {
  236. $array[] = ' ' . str_pad($val, $this->colWidth[$key], ' ', $this->cellAlign);
  237. }
  238. $content .= $style[0] . implode(' ' . $style[2], $array) . ' ' . $style[3] . PHP_EOL;
  239. }
  240. }
  241. }
  242. $content .= $this->renderSeparator('bottom');
  243. return $content;
  244. }
  245. }