Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Array Table Laravel Package

dekor/php-array-table

dekor/php-array-table is a lightweight PHP library that renders arrays as clean, customizable text tables. It is useful for CLI output, logs, reports, and debugging, with support for headers, column alignment, and simple styling—no heavy dependencies required.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require dekor/php-array-table

That is the entire setup. This is not a Laravel package — there is no service provider, no facade, no publishable config, and nothing to register in config/app.php. It is a single namespaced class with a static builder, so Composer's autoloader is all the wiring you need.

The first call looks like this:

use dekor\ArrayToTable;

$rows = [
    ['id' => 1, 'name' => 'Ada',    'role' => 'admin'],
    ['id' => 2, 'name' => 'Linus',  'role' => 'user'],
    ['id' => 3, 'name' => 'Grace',  'role' => 'admin'],
];

echo ArrayToTable::build($rows);

Which renders a +---+---+ bordered grid with a header row taken from the associative keys and one line per record. The second argument lets you restrict/reorder the visible columns (ArrayToTable::build($rows, ['id', 'name'])).

Where to look first: vendor/dekor/php-array-table/src/ArrayToTable.php. It's a few hundred lines of string concatenation and is the real documentation — read it before you depend on option names or alignment behaviour, because the README is thin and the project has been effectively dormant since its Feb 2023 release.

First use case: php artisan tinker, build a query result, and paste the output into a Slack thread or a bug ticket. It turns a wall of dd() output into something a PM can read without a screen share. That's 90% of what this class is good for.

Implementation Patterns

Ad-hoc inspection in Tinker or a throwaway route. The class works directly on arrays, so the Eloquent gotcha is just remembering ->toArray():

use dekor\ArrayToTable;

$rows = User::query()
    ->latest()
    ->limit(10)
    ->get(['id', 'name', 'email'])
    ->toArray();

echo ArrayToTable::build($rows);

Normalise before you render. The class casts every cell to a string; it does not understand Carbon, enums, money, or relations. Flatten explicitly so the table stays predictable:

$rows = Order::with('customer')->get()->map(fn ($o) => [
    'id'       => $o->id,
    'customer' => $o->customer->name,
    'status'   => $o->status->value,
    'total'    => number_format($o->total_cents / 100, 2),
    'placed'   => $o->created_at->toDateString(),
])->all();

Wrap it behind your own helper. Because there's no container binding or interface, every call site is coupled to dekor\ArrayToTable. A five-line wrapper in app/Support gives you one place to swap in Symfony Console's Table, league/CLImate, or plain json_encode(..., JSON_PRETTY_PRINT) when you inevitably want something else:

namespace App\Support;

class AsciiTable
{
    public static function render(array $rows, array $columns = []): string
    {
        return \dekor\ArrayToTable::build($rows, $columns);
    }
}

Blade output. Always <pre> plus escaping, otherwise the border characters collapse into unreadable prose and any < in a value becomes an XSS vector:

<pre>{{ \App\Support\AsciiTable::render($rows) }}</pre>

Artisan commands and log files. It works ($this->line(AsciiTable::render($rows))), but reach for $this->table($headers, $rows) first inside commands — Symfony Console's table is already there, handles wrapping, and prints with correct terminal widths. Use this package when you need the string rather than the terminal write: writing a snapshot into a log entry, an email body, or a test assertion.

Tests. Asserting on the built string is brittle but occasionally useful for golden-file style tests of report output. Keep the fixture small and assert on a substring rather than the full grid.

Gotchas and Tips

  • Column width is computed on the raw string, and multibyte handling is the number-one breakage. Values containing Cyrillic, accented Latin, CJK, or emoji will misalign the pipes unless the width calculation uses mb_strlen. Check the source before shipping anything user-facing with non-ASCII names; if it uses strlen, either fork it or pre-pad with your own mb_str_pad helper.
  • Newlines inside a cell destroy the grid. A notes or description field with a \n produces a row that's taller than one line and desynchronises every subsequent border. str_replace(["\r", "\n"], ' ', $value) everything first.
  • ANSI colour codes count as visible width. If you're tempted to colourise cells (Laravel's $this->error() style helpers, or symfony/console tags), the width math breaks. This library is plain text only.
  • Missing keys across rows cause undefined-index notices and shifted columns. Row 1 having email and row 2 not means row 2 renders short. Normalise with array_replace($template, $row) or build every row from the same array shape.
  • Nested arrays and objects don't recurse. A roles array becomes Array (or throws an "Array to string conversion" warning). Join relations to a comma string upstream.
  • Booleans and nulls render as 1 / empty. No true/false or null placeholder — cast them yourself if the table is going to a human.
  • No wrapping or truncation. A 400-character JSON blob in one column produces a 400-character-wide table and a horizontal scrollbar in Slack. Truncate with Str::limit($value, 40) at the mapping step.
  • Pass arrays, not Collections. build() is typed against arrays; an Eloquent Collection will either fatal or be coerced unpredictably depending on the version. ->toArray() or ->all() always.
  • It's effectively unmaintained (28 stars, zero dependents, last tagged release over two years ago). Treat that as a risk signal: pin the version in composer.json, don't expect upstream fixes for the multibyte issue, and be ready to fork the single class into app/Support — it's small enough that vendoring it is genuinely the lowest-risk option for anything beyond debug output.
  • Don't return it from a JSON API. It's plain text with significant whitespace; it's for humans reading a terminal, a <pre> block, or a pasted ticket. If you need machine-readable output, json_encode is the answer.
  • There are no extension points — no interfaces, no events, no formatter callbacks. The only way to change behaviour is to subclass or fork, which is another argument for the thin wrapper above.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core