laminas/laminas-text
Laminas\Text provides utilities for working with text in PHP, including FIGlet ASCII-art rendering, flexible console table generation, and multibyte string helpers. It helps format and manipulate textual output in CLI and web applications.
laminas/laminas-text ships two unrelated tools: Figlet (ASCII-art banners from .flf fonts) and Table (plain-text tables for terminals). They share a package name and nothing else.
Install with Composer (it is framework-agnostic – no service provider needed):
composer require laminas/laminas-text
Figlet first use:
use Laminas\Text\Figlet\Figlet;
$figlet = new Figlet();
$figlet->setFont('slant.flf'); // resolved from the package's resources/fonts
echo $figlet->render('Deploy');
Table first use:
use Laminas\Text\Table\Table;
$table = new Table([
'columnWidths' => [20, 10, 15],
'decorator' => 'Unicode',
]);
$table->appendRow(['Service', 'CPU', 'Status']);
$table->appendRow(['api', '12%', 'healthy']);
echo $table;
Look first at resources/fonts/ inside the vendor directory (for Figlet) and at Laminas\Text\Table\Decorator\* (for Table) – those two directories explain almost all output differences you will see.
The most common day-to-day use case in a Laravel app is artisan console output: a banner on php artisan about-style commands, or a portable table when you don't want to depend on Symfony Console's Table helper.
Figlet as a banner service. Figlet is cheap to instantiate; wrap it in a small helper so fonts are configurable per environment and you are not scattering new Figlet() everywhere.
class Banner
{
public function render(string $text, string $font = 'standard.flf'): string
{
$figlet = new Figlet();
$figlet->setFont($font);
return $figlet->render($text);
}
}
Configure font path once if you ship custom .flf files: $figlet->setFontPath(base_path('resources/figlet')); before setFont().
Figlet options worth knowing. setOutputWidth() controls line wrapping of the rendered art (not the input). setSmushMode() toggles character-smushing – Figlet::SM_SMUSH, SM_KERN, SM_FULL_WIDTH etc. Default is sensible; only touch this if your font's glyphs look overlapped or too sparse.
Table rows from Eloquent. The pattern that actually gets used: map a collection into rows, letting the table handle column alignment.
$table = new Table(['columnWidths' => [12, 30, 8]]);
$table->appendRow(['ID', 'Name', 'Qty']);
foreach (Order::limit(20)->get() as $o) {
$table->appendRow([$o->id, $o->name, $o->qty]);
}
$this->line((string) $table);
Table::__toString() calls render(), so $this->line((string) $table) is idiomatic inside an artisan command.
Composition with Symfony Console. Because it emits plain text with \n, you can pass the rendered output straight to $this->output->writeln(). If you need colour, use Symfony's <info> tags around the table output, not inside cells – the Table class does not escape markup and will miscount visible width if you embed tags in cell values.
Multi-line cells. appendRow() accepts strings containing \n; the Table builder expands the row height automatically. This is handy for "notes" columns but forces you to give that column an explicit width via columnWidths, otherwise wrapping is unpredictable.
Decorator swapping for output targets. decorator => 'Ascii' for maximum compatibility (CI logs, emails, old terminals); 'Unicode' for local/dev terminals. Make it config-driven (config('app.console_decorator')) rather than hardcoded so CI logs stay readable.
The package is archived. No security fixes, no PHP-version support guarantees. Pin the version in composer.json and plan to migrate. For tables, Symfony Console's Table (already a transitive dependency in any Laravel app) is the obvious replacement; for Figlet, standalone alternatives exist. Treat this as a stopgap unless you only ever call it in CLI paths that cannot receive untrusted input.
Font path resolution is relative-first. setFont('standard.flf') looks for resources/fonts/standard.flf relative to the package; a filename with a leading slash or ../ is taken literally. If you copy fonts into your own resources/ directory, call setFontPath() before setFont() or you will silently get the bundled default – Figlet does not throw on a missing font in all code paths.
Table width is not auto-fit. You must supply columnWidths for deterministic layout. Omit it and long cells push the borders out, which breaks alignment the moment content exceeds your assumption. Set widths per command, not globally.
ANSI colour corrupts alignment. Any escape sequence (\e[32m, Laravel's <fg=green>) inside a cell counts as visible characters to the Table builder, so padding will be wrong. Colour the whole rendered block, or post-process the output yourself.
Unicode decorator needs a UTF-8 terminal. On Windows cmd.exe (pre-Windows Terminal) box-drawing characters render as mojibake. Detect with PHP_OS_FAMILY or just default to Ascii on Windows.
Figlet output is not newline-terminated. render() returns the art without a trailing newline; $this->line() in artisan adds one, writeln() does not. Easy off-by-one in snapshot tests.
Debugging bad output: dump $table->render() to a file (file_put_contents('/tmp/t.txt', $table)) and inspect in an editor with "show whitespace" on – invisible trailing spaces from cells are the usual culprit and are impossible to see in a terminal.
Extension points are thin by design. Both subsystems are final-ish: the clean way to customise is to implement Laminas\Text\Table\Decorator\DecoratorInterface (four methods: getTopBorder, getBottomBorder, getLeftBorder, getRightBorder plus row/column variants) and pass the class name as decorator. There is no Figlet rendering interface – if you need different output shapes, you write your own renderer instead of subclassing.
Testing tip. Assert on str_contains() and line counts rather than exact byte equality of Figlet output – font files differ across versions and the archived package will not see fixes. For tables, assert on the row content lines, not the borders.
How can I help you explore Laravel packages today?