Outputting a large amount of data to the command line can quickly become a hell. Luckily there are tables that can display your data in a more readable way. The tables in Laravel are based on the Symfony Table Component.

For example, if we look at the php artisan route:list command, we always get a table back as a response with our routes in it. It is the default layout of a table for the console component in Laravel.

$ php artisan route:list
+--------+----------+----------+------+---------+--------------+
| Domain | Method   | URI      | Name | Action  | Middleware   |
+--------+----------+----------+------+---------+--------------+
|        | GET|HEAD | /        |      | Closure | web          |
|        | GET|HEAD | api/user |      | Closure | api,auth:api |
+--------+----------+----------+------+---------+--------------+

Themes

The table component comes with different table themes. The default theme is appropriately named default. Alongside the "default" theme, you also have others: compact, borderless, box, box-double. If we take the same table from the php artisan route:list command, we get the following results:

Compact

Domain Method   URI      Name Action  Middleware
       GET|HEAD /             Closure web
       GET|HEAD api/user      Closure api,api:auth

Borderless

======== ========== ========== ====== ========= ==============
 Domain   Method     URI        Name   Action    Middleware
======== ========== ========== ====== ========= ==============
          GET|HEAD   /                 Closure   web
          GET|HEAD   api/user          Closure   api,auth:api
======== ========== ========== ====== ========= ==============

Box

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Domain โ”‚ Method   โ”‚ URI      โ”‚ Name โ”‚ Action  โ”‚ Middleware   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚        โ”‚ GET|HEAD โ”‚ /        โ”‚      โ”‚ Closure โ”‚ web          โ”‚
โ”‚        โ”‚ GET|HEAD โ”‚ api/user โ”‚      โ”‚ Closure โ”‚ api,auth:api โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Box-double

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•คโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•คโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•คโ•โ•โ•โ•โ•โ•โ•คโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•คโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
โ•‘ Domain โ”‚ Method   โ”‚ URI      โ”‚ Name โ”‚ Action  โ”‚ Middleware   โ•‘
โ• โ•โ•โ•โ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ชโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ
โ•‘        โ”‚ GET|HEAD โ”‚ /        โ”‚      โ”‚ Closure โ”‚ web          โ•‘
โ•‘        โ”‚ GET|HEAD โ”‚ api/user โ”‚      โ”‚ Closure โ”‚ api,auth:api โ•‘
โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•งโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•งโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•งโ•โ•โ•โ•โ•โ•โ•งโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•งโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

With these default styles, you can already do a lot of cool things. Before we continue with creating our own theme, we should have a basic command to play with. Let's set up a command that displays all our users in a table for us.

class ListUsers extends Command
{
    protected $signature = 'secrets:list-users';

    protected $description = 'List all users';

    public function handle()
    {
        $users = User::all();

        $headers = ['name', 'email', 'email verified at'];

        $data = $users->map(function (User $user) {
            return [
                'name' => $user->name,
                'email' => $user->email,
                'email_verified_at' => $user->hasVerifiedEmail()
                    ? $user->email_verified_at->format('Y-m-d')
                    : 'Not verified',
            ];
        });

        $this->table($headers, $data);
    }
}

We have a minimal console command now that fetches all of our users and displays them. So if we had 4 users, it would look like this by default:

+------------------+----------------------------+-------------------+
| name             | email                      | email verified at |
+------------------+----------------------------+-------------------+
| Nils Nader       | edmund38@example.net       | 2019-09-29        |
| Judah Quigley    | haley.karine@example.net   | 2019-09-29        |
| Lilyan Walker    | lolita@example.net         | 2019-09-29        |
| Kristofer Winter | gibson.savanna@example.org | 2019-09-29        |
+------------------+----------------------------+-------------------+

Laravel makes it easy to change the theme of our table. Let's pick one of the above theme names and pass it along as the third argument in our console command.

public function handle()
{
    // Fetch data

    $this->table($headers, $data, 'box');
}

Custom Themes

The default themes already provide you with a lot of flexibility. However, you can do much more with tables. Let's dive into how you can create your own table style and make something useful. How can we register our custom theme?

public function handle()
{
    $this->registerCustomTableStyle();

    // Fetch data

    $this->table($headers, $data, 'secrets');
}

private function registerCustomTableStyle()
{
    $tableStyle = (new TableStyle())
        ->setCellHeaderFormat('<fg=black;bg=yellow>%s</>');

    Table::setStyleDefinition('secrets', $tableStyle);
}

In the above example, the registerCustomTableStyle method is called, which registers the custom theme. The custom theme is called secrets, which is also the name used as the third argument on the table method. In this case, the custom theme only sets the background color and text color of the header row.

Now that you know how to create custom themes, let's create a custom table. This theme will help you focus on the content and less on the lines. Let's try this:

private function registerCustomTableStyle()
{
    $tableStyle = (new TableStyle())
        ->setHorizontalBorderChars('โ”€')
        ->setVerticalBorderChars('โ”‚')
        ->setCrossingChars(' ', 'โ”Œ', 'โ”€', 'โ”', 'โ”‚', 'โ”˜', 'โ”€', 'โ””', 'โ”‚');
    Table::setStyleDefinition('secrets', $tableStyle);
}

This will result in the following table:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ id โ”‚ name           โ”‚ email                      โ”‚ email verified at โ”‚
โ”‚โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
โ”‚ 1  | Nils Nader     โ”‚ edmund38@example.net       โ”‚ 2019-09-29        โ”‚
โ”‚ 2  โ”‚ Judah Quigley  โ”‚ haley.karine@example.com   โ”‚ 2019-09-29        โ”‚
โ”‚ 3  โ”‚ Lilyan Walker  โ”‚ lolita.wiza@example.com    โ”‚ 2019-09-29        โ”‚
โ”‚ 4  โ”‚ Kristofer Ball โ”‚ gibson.savanna@example.org โ”‚ 2019-09-29        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Layout Elements

Customizing the theme of the table is one thing, but we can do even more with tables. Let's look at adding row separators, titles and footers. We'll start with the row separators.

For the separator, we can just add it as one of the lines in the table. Then the console will automatically insert a line with the same styling as the other lines.

new TableSeparator()

Since we use a collection to insert the data, we can use the splice method to insert the separator anywhere we want. That code looks like this:

$data->splice(3, 0, [new TableSeparator()]);

$this->table($headers, $data);

In the code above, we add the table separator just after the third item using the splice method of the collection. That will result in the following:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ id โ”‚ name            โ”‚ email                     โ”‚ email verified at โ”‚
โ”‚โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
โ”‚ 1  โ”‚ Ashleigh Harris โ”‚ arnold20@example.org      โ”‚ 2019-10-13        โ”‚
โ”‚ 2  โ”‚ Rico Hermist    โ”‚ kuhic.barry@example.com   โ”‚ 2019-10-13        โ”‚
โ”‚ 3  โ”‚ Robb Collin     โ”‚ donnell55@example.org     โ”‚ 2019-10-13        โ”‚
โ”‚โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
โ”‚ 4  โ”‚ Kaylin Kuhlman  โ”‚ ahmed.jacobi@example.org  โ”‚ 2019-10-13        โ”‚
โ”‚ 5  โ”‚ Clifton Harvey  โ”‚ arohan@example.net        โ”‚ 2019-10-13        โ”‚
โ”‚ 6  โ”‚ Tristian Brown  โ”‚ kianna.brakus@example.com โ”‚ 2019-10-13        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Apart from adding separators, we can also set a header title and even a footer title of the table. We can put anything in there. In a table, for example, a footer can be helpful to tell the user that this is only showing a part of the results, like pagination. It might even offer some extra useful statistics.

We can set a header and footer title like so:

$table->setHeaderTitle('Header Title');
$table->setFooterTitle('Footer Title');

However, this presents us with a new challenge. Laravel has the helper method called table for outputting tables in the console that we used in the previous example. This method doesn't allow for passing in a header or footer. For that, we need the actual table object. We can quickly get the same result and add the header and footer by creating and rendering the table ourselves.

$table = new Table($this->output);

$table->setHeaders($headers)
    ->setRows($data->toArray())
    ->setStyle('secrets');

$table->setHeaderTitle('All users');
$table->setFooterTitle(
    sprintf('%d%% verified by email', $percentageVerified)
);

$table->render();

By adding the header and footer in the table, some parts of the table's lines will be removed and updated with the text. The calculation of where the text should be is all being done in the table component. Eventually, we end up with something like this:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ All users โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ id โ”‚ name            โ”‚ email                     โ”‚ email verified at โ”‚
โ”‚โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
โ”‚ 1  โ”‚ Ashleigh Harris โ”‚ arnold20@example.org      โ”‚ 2019-10-13        โ”‚
โ”‚ 2  โ”‚ Rico Hermist    โ”‚ kuhic.barry@example.com   โ”‚ 2019-10-13        โ”‚
โ”‚ 3  โ”‚ Robb Collins    โ”‚ donnell55@example.org     โ”‚ Not verified      โ”‚
โ”‚ 4  โ”‚ Kaylin Kuhlman  โ”‚ ahmed.jacobi@example.org  โ”‚ Not verified      โ”‚
โ”‚ 5  โ”‚ Clifton Harvey  โ”‚ arohan@example.net        โ”‚ 2019-10-13        โ”‚
โ”‚ 6  โ”‚ Tristian Brown  โ”‚ kianna.brakus@example.com โ”‚ 2019-10-13        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 67% verified by email โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Rendering the table ourselves is very cool. However, it doesn't add much value. It only brings extra code that we need to maintain. We can use a different solution to add additional information to our table. This way, we can keep using the $this->table console helper method provided by Laravel.

For this, we can use the TableCell helper class. This class acts like a new cell in a row. All the items you put in the array are converted to TableCell objects and added to the table. We can reuse this logic and build our header and footer.

$headers = [
    [new TableCell(
        'A list of all your users, showing if they are verified.',
        ['colspan' => 4]
    )],
    ['id', 'name', 'email', 'email verified at']
];

$data->push(new TableSeparator());
$data->push([new TableCell(
    sprintf('%d%% verified by email', $percentageVerified),
    ['colspan' => 4]
)]);

$this->table($headers, $data, 'secrets');

As you can see in the above code, we now have an array of headers. The reason we do this, is so they both get the same styling. So if our header is green text, all our headers will be green. We specify that the colspan should be set to 4. This way, it will be printed over the full table.

We push a TableSeparator and a TableCell with the data set's information for the footer part. We need to do it this way because we don't know how many lines you are going to have in the end.

Finally, we pass the collected data to the table helper method and print the table. This results in the following:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ A list of all your users, showing if they are verified.              โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ id โ”‚ name            โ”‚ email                     โ”‚ email verified at โ”‚
โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
โ”‚ 1  โ”‚ Ashleigh Harris โ”‚ arnold20@example.org      โ”‚ 2019-10-13        โ”‚
โ”‚ 2  โ”‚ Rico Hermist    โ”‚ kuhic.barry@example.com   โ”‚ 2019-10-13        โ”‚
โ”‚ 3  โ”‚ Robb Collins    โ”‚ donnell55@example.org     โ”‚ Not verified      โ”‚
โ”‚ 4  โ”‚ Kaylin Kuhlman  โ”‚ ahmed.jacobi@example.org  โ”‚ Not verified      โ”‚
โ”‚ 5  โ”‚ Clifton Harvey  โ”‚ arohan@example.net        โ”‚ 2019-10-13        โ”‚
โ”‚ 6  โ”‚ Tristian Brown  โ”‚ kianna.brakus@example.com โ”‚ 2019-10-13        โ”‚
โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
โ”‚ 66% verified by email                                                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Why Customize the Tables?

The more you work with data on the command line, the more essential tables become. Tables can help you get the information processable on the screen. In combination with other components like pagination and questions, this can be powerful.

Customizing the table can help you as a developer to be more specific about a particular part of the data. For example, adding color to a single row or table cell gives it more attention in the overview.

Although this brings some extra work and maybe some more investigation time, generating these tables can help you out in the long run. A lot of developers just echo out everything with strings and use that as output. However, this is harder to process and also harder to share with others. A table can be easily shared as a snippet and is readable right away.