Skip to content

Instantly share code, notes, and snippets.

@redestructa
Created February 13, 2019 10:42
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save redestructa/2a7691e7f3ae69ec5161220c99e2d1b3 to your computer and use it in GitHub Desktop.
Save redestructa/2a7691e7f3ae69ec5161220c99e2d1b3 to your computer and use it in GitHub Desktop.
The table Printer class has no dependencies and generates an array out of an object array
<?php
/**
* The table Printer class has no dependencies and generates an array (strings)
* out of an object array / countable and the child properties that should be printed given by an array (strings)
*/
class TablePrinter
{
/**
* @param \Countable|array|object[] $historyItems
* @param array|string[] $columns
* @return array|string[]
*/
public function printLinesIntoArray($historyItems, $columns): array
{
$lines = [];
$columnSizes = $this->calculateColumnSizes($columns, $historyItems);
$separator = $this->buildSeparator($columns, $columnSizes);
$lines[] = $separator;
$lines[] = $this->buildHeaderLine($columns, $columnSizes);
$lines[] = $separator;
foreach ($historyItems as $item) {
$lines[] = $this->buildContentLineWithItem($columns, $columnSizes, $item);
}
$lines[] = $separator;
return $lines;
}
/**
* @param array $columns
* @param \Countable|array|object[] $historyItems
* @return array
*/
private function calculateColumnSizes(array $columns, $historyItems): array
{
$columnSizes = [];
$curCol = 0;
foreach ($columns as $column) {
$columnSizes[] = strlen($column);
$curCol++;
}
foreach ($historyItems as $item) {
$curCol = 0;
foreach ($columns as $column) {
/** @noinspection PhpVariableVariableInspection */
$columnSizes[$curCol] = max($columnSizes[$curCol], strlen($item->$column));
$curCol++;
}
}
return $columnSizes;
}
/**
* @param array $columns
* @param array $columnSize
* @return string
*/
private function buildSeparator(array $columns, array $columnSize): string
{
return $this->strRepeat('-',
count($columns) * 3 + 1 + array_reduce($columnSize, [$this, 'sum'])
);
}
private function strRepeat(string $str, int $count)
{
$str2 = '';
for ($i = $count; $i > 0; $i--) {
$str2 .= $str;
}
return $str2;
}
/**
* @param array $columns
* @param array $columnSize
* @return string
*/
private function buildHeaderLine(array $columns, array $columnSize): string
{
return $this->buildContentLineWithItem($columns, $columnSize);
}
/**
* @param array $columns
* @param array $columnSize
* @param object $item
* @return string
*/
private function buildContentLineWithItem(array $columns, array $columnSize, object $item = null): string
{
$data = [];
$formatString = '';
$curCol = 0;
foreach ($columns as $column) {
$formatString .= '| %' . $columnSize[$curCol] . 's ';
/** @noinspection PhpVariableVariableInspection */
$data[] = $item ? $item->$column : $column;
if ($curCol === sizeof($columns) - 1) {
$formatString .= '| ';
}
$curCol++;
}
return sprintf($formatString, ...$data);
}
private function sum($a, $b)
{
return $a + $b;
}
}
@pbarney
Copy link

pbarney commented Jan 7, 2021

Thanks for sharing this code, I found it useful! A couple things: Because of lines 46 and 98, $historyItems will not work with arrays. And because of this, the column identifiers cannot have spaces in them. I was looking forward to using something like:

$items[] = [
   'File Name' => 'index.html',
   'Accessed Time' => $stat['atime'],
   'Modified Time' => $stat['mtime],
   'Size' => number_format($stat['size'])
];
// etc..
$output = $tablePrinter->printLinesIntoArray($items, ['Modified Time', 'Accessed Time', 'Size', 'File'], false);

Just something to consider...

@skwid138
Copy link

skwid138 commented May 4, 2021

@redestructa Thank you so much for sharing this, I found it on a stack thread and it's exactly what I was looking for. Something lightweight and simple to build tables. I'm using it to build and output tables into a little CLI tool.

I've renamed some things to make it easier for me to use as well as made some fairly minor tweaks to how things work so it should address what @pbarney mentioned as well.

I also added a little more customizability to it, such as the ability to color the output, change the character used at column and row intersections, the ability to choose the header and data text justification, and a method to echo the strings.

I've only been testing it so far on my local environment which is running macOS 11.3 with PHP 7.6.16 / PHP 8.0.3

Anyway, here's the updated script

Here's what a sample looks like:
php_table_example

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment