Table(表格)

3.4 版本
维护中的版本

当构建命令行程序时,显示表格数据可能是有用的:

1
2
3
4
5
6
7
8
+---------------+--------------------------+------------------+| 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 |
| 80-902734-1-6 | And Then There Were None | Agatha Christie  |
+---------------+--------------------------+------------------+

要显示一个表格,使用 Table,设置头(headers),设置行(rows),即可生成表格:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
use Symfony\Component\Console\Helper\Table;
// ...
 
class SomeCommand extends Command
{
    public function execute(InputInterface $input, OutputInterface $output)
    {
        $table = new Table($output);
        $table
            ->setHeaders(array('ISBN', 'Title', 'Author'))
            ->setRows(array(
                array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
                array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
                array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
                array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
            ))
        ;
        $table->render();
    }
}

通过传入一个 TableSeparator 实例作为row,你可以在表格输出的任何地方添加分隔符(separator):

1
2
3
4
5
6
7
8
9
use Symfony\Component\Console\Helper\TableSeparator;
 
$table->setRows(array(
    array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
    array('9971-5-0210-0', 'A Tale of Two Cities', 'Charles Dickens'),
    new TableSeparator(),
    array('960-425-059-0', 'The Lord of the Rings', 'J. R. R. Tolkien'),
    array('80-902734-1-6', 'And Then There Were None', 'Agatha Christie'),
));
1
2
3
4
5
6
7
8
9
+---------------+--------------------------+------------------+| 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 |
| 80-902734-1-6 | And Then There Were None | Agatha Christie  |
+---------------+--------------------------+------------------+

3.1 setColumnWidths()setColumnWidth() 方法从Symfony 3.1起被引入。

默认时,列(column)的宽度将根据其内容自动计算出来。使用 setColumnWidths() 方法可以显式指定列宽:

1
2
3
// ...
$table->setColumnWidths(array(10, 0, 30));
$table->render();

本例中,第一列的宽度是 10,最后一列的是 30,而第二列的宽度将被自动计算,因为设了 0 值。命令行输出如下:

1
2
3
4
5
6
7
8
9
+---------------+--------------------------+--------------------------------+| 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               |
| 80-902734-1-6 | And Then There Were None | Agatha Christie                |
+---------------+--------------------------+--------------------------------+

注意已定义的列宽,总是被认为是最小的列宽度。如果内容难以匹配,则给定的列宽将被增加到最大内容长度。这就是为什么在上例中,第一列是 13 个字符长度,而用户只定义了 10 的宽度。

你可以使用 setColumnWidth() 方法分别地设置每一列的宽度。第一个参数是列的索引 (从 0 开始),第二个参数是列的宽度:

1
2
3
4
// ...
$table->setColumnWidth(0, 10);
$table->setColumnWidth(2, 30);
$table->render();

通过 setStyle() 可以改变表格默认的样式:

1
2
3
4
5
6
// same as calling nothing / 与不设置样式时相同
$table->setStyle('default');
 
// changes the default style to compact / 改变默认样式为紧凑型
$table->setStyle('compact');
$table->render();

代码的结果是:

1
2
3
4
5
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
80-902734-1-6 And Then There Were None Agatha Christie

你也可以设置样式为 borderless:

1
2
$table->setStyle('borderless');
$table->render();

它输出:

1
2
3
4
5
6
7
8
=============== ========================== ==================
 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
 80-902734-1-6   And Then There Were None   Agatha Christie
=============== ========================== ==================

如果内置的风格不适合你的需求,定义你自己的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use Symfony\Component\Console\Helper\TableStyle;
 
// by default, this is based on the default style
$style = new TableStyle();
 
// customize the style
$style
    ->setHorizontalBorderChar('<fg=magenta>|</>')
    ->setVerticalBorderChar('<fg=magenta>-</>')
    ->setCrossingChar(' ')
;
 
// use the style for this table
$table->setStyle($style);

以下是你可以自定义内容的完整列表:

你也可以注册一个全局样式:

1
2
3
4
5
6
// register the style under the colorful name
// 注册colorful这个名称的样式
Table::setStyleDefinition('colorful', $style);
 
// use it for a table / 在表格中使用
$table->setStyle('colorful');

本方法也可用于覆写内置样式。

扩展多列和多行 

要让表格单元扩展到多个列,可以使用 TableCell:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableSeparator;
use Symfony\Component\Console\Helper\TableCell;
 
$table = new Table($output);
$table
    ->setHeaders(array('ISBN', 'Title', 'Author'))
    ->setRows(array(
        array('99921-58-10-7', 'Divine Comedy', 'Dante Alighieri'),
        new TableSeparator(),
        array(new TableCell('This value spans 3 columns.', array('colspan' => 3))),
    ))
;
$table->render();

它输出:

1
2
3
4
5
6
7
+---------------+---------------+-----------------+| ISBN          | Title         | Author          |
+---------------+---------------+-----------------+
| 99921-58-10-7 | Divine Comedy | Dante Alighieri |
+---------------+---------------+-----------------+
| This value spans 3 columns.                     |
+---------------+---------------+-----------------+

把header cell(头所在的单元格)扩展为整个表格宽度,你可以创建一个多行的页面标题:

1
2
3
4
5
$table->setHeaders(array(
    array(new TableCell('Main table title', array('colspan' => 3))),
    array('ISBN', 'Title', 'Author'),
))
// ...

这会生成:

1
2
3
4
5
6
7
+-------+-------+--------+| Main table title       |
+-------+-------+--------+
| ISBN  | Title | Author |
+-------+-------+--------+
| ...                    |
+-------+-------+--------+

以类似方式你可以扩展多行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableCell;
 
$table = new Table($output);
$table
    ->setHeaders(array('ISBN', 'Title', 'Author'))
    ->setRows(array(
        array(
            '978-0521567817',
            'De Monarchia',
            new TableCell("Dante Alighieri\nspans multiple rows", array('rowspan' => 2)),
        ),
        array('978-0804169127', 'Divine Comedy'),
    ))
;
$table->render();

这将输出:

1
2
3
4
5
6
+----------------+---------------+---------------------+| ISBN           | Title         | Author              |
+----------------+---------------+---------------------+
| 978-0521567817 | De Monarchia  | Dante Alighieri     |
| 978-0804169127 | Divine Comedy | spans multiple rows |
+----------------+---------------+---------------------+

你可以同时使用 colspanrowspan 选项,即可创建你所希望的任何表格(table layer)。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)