Skip to content

Wrong formatting of vertical style tables with headers containing multi-byte characters #54433

Closed
@mcpicoli

Description

@mcpicoli

Symfony version(s) affected

6.4.2

Description

When using vertical style tables, whenever the component has to calculate the header width dynamically, the calculated width uses the total number of bytes of the string involved instead of the actual number of characters that would be rendered. That results in misaligned columns (and ugly tables) if the length of actual renderable characters is smaller than the next smallest length.

How to reproduce

Please note that I am using a Laravel console command for convenience only. The code that matters uses only Symfony objects and methods!

Create and run the following code inside any Laravel project. The console command may be created using php artisan make:command TestBrokenTable. Again, this is only by convenience, the affected code does not depend on Laravel! (I do not have any Symfony framework project available!)

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Output\BufferedOutput;

class TestBrokenTable extends Command
{
	/**
	 * The name and signature of the console command.
	 *
	 * @var string
	 */
	protected $signature = "app:test-broken-table";

	/**
	 * The console command description.
	 *
	 * @var string
	 */
	protected $description = "Command description";

	/**
	 * Execute the console command.
	 */
	public function handle()
	{
		$headers = [
			"long without MB chars",
			"áéíóú MB chars",					// <-- This will cause problems
			"Column 3 anything",
		];

		// This will NOT cause problems...

		// $headers = [
		// 	"long without MB chars",
		// 	"aeiou MB chars",
		// 	"Column 3 anything",
		// ];

		$this->line("Middle Header:");
		$this->line("Bytes: ".strlen($headers[1]));
		$this->line("Chars: ".mb_strlen($headers[1]));
		
		$data = [
			[
				"Shorter value",
				"Value with MB chars áéíóú",
				"Another Value",
			],
		];
		
		$output = new BufferedOutput(decorated: true);
		
		$table = new Table($output);
		$table->setHeaders($headers);
		$table->setRows($data);
		$table->setVertical();
		
		$table->render();
		
		$text = $output->fetch();
		
		print($text);
	}
}

The output is as follows:

image

If I remove the multi-byte characters, the output is now correct:

image

If I use a table with horizontal (standard) layout, the problem does not occur.

Possible Solution

No response

Additional Context

All of the strings are in UTF-8 format.
Using Microsoft Visual Studio Code (latest update as of 2024-03-28).
Using Windows 10 Professional (latest update as of 2024-03-28).

In the above examples, "bytes" are the result of the strlen() function and "chars" the result of mb_strlen().

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions