ocramius/code-generator-utils
A small toolkit of utilities that simplifies programmatic PHP code generation. It offers helpers for building class and method definitions, sanitizing identifiers, and producing unique names—handy when writing proxy generators, scaffolding tools, or anything that emits PHP source at runtime.
Architecture fit. ocramius/code-generator-utils is a thin convenience layer over nikic/php-parser and PHP's Reflection API — it does not generate code by itself so much as make it ergonomic to hand reflection-derived information to an AST builder. That places it squarely in the tooling/build-time layer, not the runtime layer of a Laravel application. Laravel's native generation story is stub-based (artisan make:* copies templates), so the package only earns its place where you need reflection-aware generation: custom artisan generators that inspect existing classes, proxy/decorator generation for a container or ORM, DTO/typed-property scaffolding, annotation-to-attribute migration, or IDE-helper-style metadata emission. For a standard Laravel CRUD app it adds nothing.
Integration feasibility. Mechanically trivial: PSR-4, MIT, zero framework coupling, a normal Composer install. The blocker is not technical fit but lifecycle. The repository is archived, the last release (2025-02-05) reads as a terminal tag, and 0 dependents means almost no field validation and no downstream pressure keeping it green against new PHP or php-parser majors. A TPM should treat "archived + zero dependents" as a hard signal that the maintenance burden transfers to us on day one.
Technical risk.
barryvdh/laravel-ide-helper — all compete for nikic/php-parser major versions. An archived package cannot widen its constraint, so it becomes the pin that holds your tooling stack back.php-parser v5 changes; failures will be fatal errors, not warnings.Key questions before committing.
nikic/php-parser constraint does the package declare, and does it resolve against our current lockfile (composer why-not in a scratch project)?require-dev or a standalone tooling repository so it never enters the production dependency graph?nette/php-generator, laminas/laminas-code) that covers the same use case?Stack fit. Constrain to require-dev (or a separate tooling package/repo), targeting Laravel 10–12 on PHP 8.2+. It must never appear in the runtime require block; code generation belongs in CI and developer workflows, and generated artifacts get committed or shipped as build output.
Alternatives to evaluate first. The package's value is glue, and glue is replaceable:
nette/php-generator — actively maintained, MIT, covers the majority of reflection-to-class generation use cases with a higher-level API.nikic/php-parser directly — for AST manipulation and transformation; you write the ~100–200 lines of reflection glue yourself.laminas/laminas-code — reflection-driven generators, maintained.rectorphp/rector — for AST transforms (upgrades, refactors) rather than net-new generation.Recommendation: run a one-day spike reproducing the target use case twice — once with code-generator-utils, once with nette/php-generator plus raw php-parser. Adopt the archived package only if it wins by a margin large enough to justify permanent self-maintenance.
Migration path (if adopted).
App\Tooling\CodeGenerator) so the underlying library is swappable and the archived dependency is confined to one adapter.php-parser; add a CI job that runs composer update --dry-run to surface future resolution failures early.Compatibility. Test against the oldest and newest PHP in your support matrix, and against the exact php-parser major required by Rector/PHPStan/Pint in your CI. Pin the generated-output format with golden-file tests so a transitive php-parser bump cannot silently change emitted code.
Sequencing. Start with a single, low-blast-radius generator — DTOs or test factories — where output is easy to eyeball. Expand to higher-risk generators (proxies, service wiring) only after the dependency has survived one PHP minor upgrade and one tooling upgrade cycle.
Maintenance. Ownership transfers to us on adoption. Budget either a fork-maintenance line item (roughly a few days per year plus reactive work on PHP releases) or a scheduled replacement milestone. An archived package receives no PHP-version PRs, no bug fixes, and no php-parser constraint widening.
Support. No upstream triage. All questions route to internal expertise or reading the source. This is acceptable for a utility with a small, stable API surface and unacceptable for anything touching production behavior.
Scaling. No runtime footprint — build-time only. Generation cost is linear in class count; fine for hundreds of classes, but full-application generation on every CI run will add minutes. Cache generated artifacts and regenerate only on relevant input changes (class signature hashing, not just timestamps).
Failure modes to design against.
php-parser — surfaces as a blocked dependency upgrade, not a runtime error.Ramp-up. Moderate to high for engineers without AST experience; the Reflection-plus-PHP-Parser mental model is a specialized skill. Concentrate ownership in one or two engineers rather than spreading it across the team, and mitigate the bus factor with golden-file tests and a short internal README documenting why the dependency exists and what replaces it.
Verdict. Given the archived status, zero dependents, and a low opportunity score, treat this as a build-vs-adopt spike, not a default dependency. For most Laravel teams the correct outcome is nette/php-generator (or raw php-parser) behind an internal interface; adopt code-generator-utils only if a specific API it exposes materially shortens the spike, and only inside require-dev with a named internal owner.
How can I help you explore Laravel packages today?