libxa / toolkit
Debugger, profiler and code generators for LibxaFrame.
Requires
- php: ^8.3
- ext-json: *
- libxa/framework: ^0.10.1 || ^0.11.0
Requires (Dev)
- phpunit/phpunit: ^11.0 || ^12.0
README
A debugger, a profiler and code generators for LibxaFrame.
composer require libxa/toolkit --dev
Requires LibxaFrame ^0.10.1 and PHP 8.3.
Profiler
Records the spans you open, rather than instrumenting everything. The cost is proportional to what you asked for, and an unmeasured section shows up as a gap instead of as time attributed to whatever happened to be nearby.
$result = tk_measure('render invoice', fn () => $renderer->render($invoice));
Timings come from hrtime, not microtime. The system clock can move
backwards, and a negative duration in a profiler sends people looking for a bug
in their own code.
Nested spans record their depth, so the output reads as a tree. A span whose callable throws is still closed: without that, one exception leaves it open and everything after it is nested a level too deep, which makes the output unreadable exactly when something has gone wrong.
It reports through Server-Timing
Server-Timing: request0;dur=42.11, database1;dur=8.02, db;dur=8.02;desc="3 queries", total;dur=42.30
Browsers show this natively in the network panel, which means it works for JSON responses, redirects and downloads, none of which have anywhere to put a debug bar. It also cannot alter the response body, so switching the profiler on cannot change what your application returns.
$router->group(['middleware' => [ProfilerMiddleware::class]], function ($router) { // every response carries its own profile });
Off by default outside local
TOOLKIT_PROFILER left unset follows the environment: on in local, testing and
development, off everywhere else. Doing nothing gives you the safe answer. A
developer tool that leaves itself on in production leaks timings, memory
figures and occasionally more than that to anyone who asks for a page.
Dumper
tk_dump($value); // print and carry on tk_dd($value); // print and stop
var_dump is unreadable at any depth and print_r loses types, which is
usually the thing being checked:
null
true
"" (0)
" " (1)
1.0
array(2) [
"name" => "Ada" (3),
"roles" => array(1) [
0 => "admin" (5)
]
]
Every string reports its length, because "" and " " look identical
otherwise. Whole floats print as 1.0 so they are not mistaken for the integer
1. NAN and INF are shown rather than silently breaking the output.
Private and protected properties are included, since the interesting state is almost always what the class was hiding. Depth, item count and string length are all capped, so dumping something enormous while investigating a memory problem does not make the problem worse.
The helpers are prefixed tk_ so installing this cannot fatally redeclare a
dump() your application already has.
Generators
php libxa toolkit:make service Invoice # App\Services\InvoiceService php libxa toolkit:make action SendInvoice # App\Actions\SendInvoiceAction php libxa toolkit:make dto InvoiceData # App\DTO\InvoiceData php libxa toolkit:make repository User # App\Repositories\UserRepository php libxa toolkit:make service Billing/Invoice # App\Services\Billing\InvoiceService
Services, actions, DTOs and repositories are structure rather than framework
features, which is why the framework has no make: for them. They are still
written by hand a hundred times per project, always slightly differently.
The suffix is added when missing and never twice, so service Invoice and
service InvoiceService both produce InvoiceService. Subdirectories work in
either slash and appear in the namespace as well as the path.
DTOs come out final readonly, since a DTO you can modify after construction
is a mutable array with extra steps. Actions get one method: an action that
grows a second one is a service, and having to rename it is the signal.
Configuration
php libxa vendor:publish --tag=toolkit-config
Tests
composer test
42 tests. Every generated stub is written to disk and run through php -l,
because generating code that does not parse is the one failure a generator must
never have and is invisible until someone opens the file.
Licence
MIT.