nette/php-generator
Nette PHP Generator lets you build PHP classes, interfaces, traits, enums, methods and complete files programmatically, with clean pretty-printing, full modern PHP support and a fluent API. Ideal for scaffolding, ORMs and code generators.
Start by installing via Composer: composer require nette/php-generator. The package requires PHP 8.1+ and integrates with PHP-Parser 5+. As of v4.2.3 it also runs cleanly on PHP 8.6, so it's safe to adopt even if your CI matrix is already testing ahead of the curve. Begin with the core types: PhpFile, PhpNamespace, and ClassType. A minimal first use is generating a simple class:
use Nette\PhpGenerator\ClassType;
use Nette\PhpGenerator\PhpFile;
use Nette\PhpGenerator\PhpNamespace;
$namespace = new PhpNamespace('App\Entity');
$namespace->add(new ClassType('User')
->addProperty('id', 0)
->addMethod('getId')
->setPublic()
->setReturnType('int')
->setBody('return $this->id;'));
$file = (new PhpFile)
->add($namespace);
echo $file;
// Outputs clean PHP code with proper formatting and use statements
Check the README and examples in the repo first—especially examples/generate.php.
Factory::fromClassReflection() to reverse-engineer existing classes (e.g., for scaffolding or migration tools). Combine with ClassManipulator to programmatically add methods/properties to existing types before generation.add() API: Leverage PhpFile::add() to handle all top-level constructs (classes, enums, traits, functions, namespaces) in one call. It auto-assigns namespaces and manages file structure, eliminating boilerplate:
$file = new PhpFile;
$file->add('App\Services\OrderService');
$file->add(new GlobalFunction('formatCurrency'));
ClassType::fromCode() to parse existing PHP snippets into AST-like structures, then mutate them before regeneration. Useful for patching generated code (e.g., adding attributes or DocBlocks). Since v4.2.3, typed class constants (PHP 8.3 const int FOO = 1;) survive the round-trip through ClassType::from() / fromCode() instead of silently losing their type—so a "parse, tweak, reprint" pipeline is now safe for modern codebases.PsrPrinter subclasses via Printer::setDumper() for project-specific formatting (e.g., enforcing PSR-12 or internal style). Override printAttribute() to support custom attributes.Factory::fromClassReflection() with ClassManipulator—ideal for custom bundles or ORM extensions.ClassLike constructors accept FQNs (e.g., 'App\Model\User') and auto-extract namespaces—but the legacy $namespace constructor parameter is deprecated. Prefer setNamespace() to avoid surprises.PhpNamespace::add() now always assigns itself to added ClassLike objects (getNamespace() is never null). Check logic relying on null checks before upgrading.hasTrait(), hasConstant(), getMethod() early to avoid runtime errors in dynamic codegen.@var false) may not print without explicit handling. Always verify with Printer::printAttributes() in tests.fromCode()) that a golden-file test would have caught. On anything below v4.2.3, re-declare constant types manually after parsing.Dumper for custom literal formatting, or override Printer methods like printDocComment() for strict docblock compliance. Note: v4+ requires PHP 8.1+ enums for Visibility, PropertyAccessMode, etc.Dumper::dump() or Printer::dump() on any node (e.g., Method, Parameter) for runtime inspection of its structure before printing.$withBodies = false for interfaces (v4.1.8+ rejects body extraction there).How can I help you explore Laravel packages today?