ruudk/code-generator
Composer 安装命令:
composer require --dev ruudk/code-generator
包简介
Yield your code line by line: let generators handle indentation, formatting, and structure for you
关键字:
README 文档
README
Code Generator for PHP
Yield your code line by line: let generators handle indentation, formatting, and structure for you
Code Generator
Transform the way you generate PHP code! This library makes code generation feel natural and elegant - just yield your lines and watch as perfectly formatted, beautifully structured PHP emerges with automatic namespace imports, proper indentation, and clean syntax.
✨ Why This Library?
Ever struggled with generating PHP code? String concatenation getting messy? Indentation driving you crazy? This is your solution!
🎯 Write code that writes code - but make it beautiful
🎯 Yield line by line - no string concatenation nightmares
🎯 Automatic everything - imports, indentation, formatting handled for you
🎯 Composable generators - chain, wrap, and transform with ease
🎯 Zero boilerplate - focus on what to generate, not how
🚀 Key Features
🎨 Beautiful Output, Every Time
- Smart namespace management - imports are automatically collected and organized
- Perfect indentation - just yield your lines, nesting is handled automatically
- Clean formatting - proper spacing, consistent style, readable code
🔧 Powerful Generator Toolkit
indent()- Auto-indent nested code blocksjoin(),wrap(),prefix(),suffix()- Transform and compose generatorscomment(),blockComment(),docComment()- Generate any comment styledumpCall(),dumpAttribute()- Smart method calls and attributesstatement()- Auto-add semicolons where needed
🎭 Flexibility First
- Yield strings, arrays, or generators - mix and match as needed
- Compose generators - results can be wrapped, joined, and transformed
- Conditional generation -
maybeWrap()for optional structures - Multi-line strings - automatic HEREDOC/NOWDOC handling
📦 Get Started in Seconds!
Install via Composer and start generating beautiful code immediately:
composer require ruudk/code-generator --dev
That's it! You're ready to transform your PHP code generation. 🚀
💡 The Magic: Before & After
❌ Before (The Old Way)
// Manual string concatenation, tracking indentation, managing imports... $code = "<?php\n\n"; $code .= "declare(strict_types=1);\n\n"; $code .= "namespace Example\\Demo;\n\n"; // Manually tracking what needs to be imported $code .= "use DateTimeImmutable;\n"; $code .= "use Example\\Attributes\\Something;\n"; $code .= "use Example\\Demo;\n"; $code .= "use Example\\Parent;\n\n"; $code .= "// Auto-generated example file\n\n"; $code .= "#[Something]\n"; $code .= "final readonly class Demo extends Parent\n"; $code .= "{\n"; $code .= " public function __construct(\n"; $code .= " private DateTimeImmutable \$date,\n"; // Manual indentation! $code .= " ) {\n"; $code .= " parent::__construct(\n"; $code .= " 'Hello, World!',\n"; $code .= " true,\n"; $code .= " );\n"; $code .= " }\n"; $code .= "}\n"; // 😱 Imagine maintaining this for complex files!
✅ After (The Generator Way)
See the example below - clean, maintainable, and beautiful! The generator handles all the complexity for you.
<?php declare(strict_types=1); use Ruudk\CodeGenerator\CodeGenerator; include 'vendor/autoload.php'; $generator = new CodeGenerator('Example\Demo'); echo $generator->dumpFile([ '// Auto-generated example file', '', $generator->dumpAttribute('Example\Attributes\Something'), $generator->dumpAttribute('Example\Attributes\Single', ['value: "Hello, World!"']), $generator->dumpAttribute('Example\Attributes\Multiple', ['value: "Hello, World!"', 'other: "Other value"']), sprintf( 'final readonly class %s extends %s', $generator->import('Example\Demo'), $generator->import('Example\Parent'), ), '{', $generator->indent(function () use ($generator) { yield 'public function __construct('; yield $generator->indent(function () use ($generator) { yield sprintf('private %s $date,', $generator->import(DateTimeImmutable::class)); }); yield ') {'; yield $generator->indent(function () use ($generator) { yield from $generator->statement($generator->dumpCall('parent', '__construct', [ "'Hello, World!'", 'true', ], true)); }); yield '}'; }), '}', ]);
Output
<?php declare(strict_types=1); namespace Example\Demo; use DateTimeImmutable; use Example\Attributes\Multiple; use Example\Attributes\Single; use Example\Attributes\Something; use Example\Demo; use Example\Parent; // Auto-generated example file #[Something] #[Single(value: "Hello, World!")] #[Multiple( value: "Hello, World!", other: "Other value", )] final readonly class Demo extends Parent { public function __construct( private DateTimeImmutable $date, ) { parent::__construct( 'Hello, World!', true, ); } }
Another Example
<?php declare(strict_types=1); use Ruudk\CodeGenerator\CodeGenerator; use Ruudk\CodeGenerator\Group; include 'vendor/autoload.php'; $generator = new CodeGenerator('Example\Demo'); // First, let's see what happens step by step echo $generator->dumpFile(function () use ($generator) { // Comments yield '// This file demonstrates ALL CodeGenerator features'; yield '// Auto-generated example file'; yield ''; // Class with attributes yield from $generator->dumpAttribute('Example\Attributes\Entity'); yield from $generator->dumpAttribute('Example\Attributes\Table'); yield sprintf( 'final class DemoClass extends %s implements %s, %s', $generator->import('Example\BaseClass'), $generator->import('Example\Interfaces\FirstInterface'), $generator->import('Example\Interfaces\SecondInterface'), ); yield '{'; yield $generator->indent(function () use ($generator) { // Properties with indentation yield '// Class properties'; yield sprintf('private %s $date;', $generator->import(DateTimeImmutable::class)); yield ''; yield ''; // multiple newlines are ignored yield sprintf('private %s $collection;', $generator->import('Doctrine\Common\Collections\Collection')); yield sprintf('private ?%s $optional = null;', $generator->import(stdClass::class)); yield ''; // Constructor using dumpCall yield 'public function __construct('; yield $generator->indent([ sprintf('private readonly %s $service,', $generator->import('App\Services\MainService')), sprintf( 'private %s $enum = %s,', $generator->import('App\Enums\Status'), $generator->import('App\Enums\Status') . '::Active', ), 'string $name = \'default\',', ]); yield ') {'; $generator->indent(function () use ($generator) { // Parent constructor call yield from $generator->dumpCall('parent', '__construct', [ 'enabled: true', 'timeout: 30', ], static: true); yield ''; // Method chaining with dumpCall yield from $generator->statement( $generator->dumpCall( $generator->dumpCall( $generator->dumpCall('$this', 'getBuilder'), 'setName', ['$name'], ), 'setDebug', ['true'], ), ); yield ''; // Static method call yield from $generator->statement( $generator->dumpCall('Logger', 'info', [ '\'Constructor initialized\'', '[\'class\' => __CLASS__]', ], static: true), ); }); yield '}'; yield ''; // Method with various features yield '/**'; yield ' * Demonstrates various generator features'; yield ' */'; yield 'public function processData(array $data): void'; yield '{'; yield $generator->indent(function () use ($generator) { // Using prefixFirst and suffixLast yield from $generator->prefixFirst( '$result = ', $generator->suffixLast(';', ['$this->calculate($data)']), ); yield ''; // Using wrap yield from $generator->statement( $generator->wrap('$wrapped = [', ['$result'], ']'), ); yield ''; // Using maybeWrap with condition yield from $generator->maybeWrap(true, 'if ($result) { ', [ '$this->save($result);', ], ' }'); yield ''; // Using allSuffix for array elements yield '$items = ['; yield $generator->indent( $generator->allSuffix(',', [ '\'first\'', '\'second\'', '\'third\'', '// Comment not suffixed', ]), ); yield '];'; yield ''; // Using dumpFunctionCall yield from $generator->statement( $generator->dumpFunctionCall('array_map', [ 'fn($x) => $x * 2', '$items', ]), ); yield ''; // Using join $joined = $generator->join(', ', ['$a', '$b', '$c']); yield sprintf('$concatenated = sprintf(\'%%s\', %s);', $joined); yield ''; // Using joinFirstPair yield from $generator->statement( $generator->joinFirstPair([ '$prefix', ' = \'value\'', ' . \'suffix\'', ]), ); yield ''; // Using suffixFirst yield 'foreach ($items as $item) {'; yield $generator->indent( $generator->suffixFirst(':', [ 'echo $item', 'echo PHP_EOL', ]), ); yield '}'; yield ''; // Using new instance creation yield from $generator->statement( $generator->dumpCall(DateTime::class, '__construct', ['\'now\'']), ); yield ''; // Multi-line string with maybeNowDoc $multilineText = "This is a\nmulti-line\nstring example"; yield sprintf('$text = %s;', $generator->maybeNowDoc($multilineText)); yield ''; // Class reference yield sprintf( '$className = %s;', $generator->dumpClassReference('Example\SomeClass'), ); yield ''; }); yield '}'; yield ''; // Private method with Group nesting yield 'private function calculate(array $data): int'; yield '{'; yield $generator->indent(function () use ($generator) { yield 'return match($data[\'type\'] ?? null) {'; yield $generator->indent([ '\'sum\' => array_sum($data[\'values\']),', '\'count\' => count($data[\'values\']),', '\'max\' => max($data[\'values\']),', 'default => 0,', ]); yield '};'; }); yield '}'; yield ''; // Static factory method yield sprintf('public static function create(): %s', $generator->import('self')); yield '{'; yield $generator->indent([ sprintf('return new %s(', $generator->import('self')), $generator->indent([ sprintf('new %s(),', $generator->import('App\Services\MainService')), ]), ');', ]); yield '}'; }); yield '}'; yield ''; // Interface yield sprintf( 'interface CustomInterface extends %s', $generator->import('Example\Interfaces\BaseInterface'), ); yield '{'; yield $generator->indent([ 'public function process(mixed $data): void;', '', 'public function validate(array $rules): bool;', ]); yield '}'; yield ''; // Enum yield 'enum Color: string'; yield '{'; yield $generator->indent([ 'case RED = \'#FF0000\';', 'case GREEN = \'#00FF00\';', 'case BLUE = \'#0000FF\';', '', 'public function toRgb(): array', '{', $generator->indent([ 'return match($this) {', $generator->indent([ 'self::RED => [255, 0, 0],', 'self::GREEN => [0, 255, 0],', 'self::BLUE => [0, 0, 255],', ]), '};', ]), '}', ]); yield '}'; yield ''; // Trait yield 'trait TimestampableTrait'; yield '{'; yield $generator->indent(function () use ($generator) { yield sprintf('private %s $createdAt;', $generator->import(DateTimeInterface::class)); yield sprintf('private ?%s $updatedAt = null;', $generator->import(DateTimeInterface::class)); yield ''; yield 'public function updateTimestamps(): void'; yield '{'; yield $generator->indent([ 'if ($this->createdAt === null) {', $generator->indent( $generator->statement(['$this->createdAt = new \\DateTimeImmutable()']), ), '}', '$this->updatedAt = new \\DateTimeImmutable();', ]); yield '}'; }); yield '}'; yield ''; // Anonymous class yield from $generator->statement([ '$anonymous = new class(', $generator->indent(['$dependency']), ') {', $generator->indent([ 'public function __construct(private mixed $dep) {}', '', 'public function execute(): void', '{', $generator->indent(['echo \'Anonymous class method\';']), '}', ]), '}', ]); yield ''; // Global function yield 'function helperFunction(string $input): string'; yield '{'; yield $generator->indent( $generator->statement([ 'return strtoupper($input)', ]), ); yield '}'; });
Output
<?php declare(strict_types=1); namespace Example\Demo; use App\Enums\Status; use App\Services\MainService; use DateTime; use DateTimeImmutable; use DateTimeInterface; use Doctrine\Common\Collections\Collection; use Example\Attributes\Entity; use Example\Attributes\Table; use Example\BaseClass; use Example\Interfaces\BaseInterface; use Example\Interfaces\FirstInterface; use Example\Interfaces\SecondInterface; use Example\SomeClass; use Logger; use self; use stdClass; // This file demonstrates ALL CodeGenerator features // Auto-generated example file #[Entity] #[Table] final class DemoClass extends BaseClass implements FirstInterface, SecondInterface { // Class properties private DateTimeImmutable $date; private Collection $collection; private ?stdClass $optional = null; public function __construct( private readonly MainService $service, private Status $enum = Status::Active, string $name = 'default', ) { } /** * Demonstrates various generator features */ public function processData(array $data): void { $result = $this->calculate($data); $wrapped = [$result]; if ($result) { $this->save($result); } $items = [ 'first', 'second', 'third', // Comment not suffixed ]; array_map( fn($x) => $x * 2, $items, ); $concatenated = sprintf('%s', $a, $b, $c); $prefix = 'value' . 'suffix'; foreach ($items as $item) { echo $item: echo PHP_EOL } new DateTime('now'); $text = <<<'EOD' This is a multi-line string example EOD; $className = SomeClass::class; } private function calculate(array $data): int { return match($data['type'] ?? null) { 'sum' => array_sum($data['values']), 'count' => count($data['values']), 'max' => max($data['values']), default => 0, }; } public static function create(): self { return new self( new MainService(), ); } } interface CustomInterface extends BaseInterface { public function process(mixed $data): void; public function validate(array $rules): bool; } enum Color: string { case RED = '#FF0000'; case GREEN = '#00FF00'; case BLUE = '#0000FF'; public function toRgb(): array { return match($this) { self::RED => [255, 0, 0], self::GREEN => [0, 255, 0], self::BLUE => [0, 0, 255], }; } } trait TimestampableTrait { private DateTimeInterface $createdAt; private ?DateTimeInterface $updatedAt = null; public function updateTimestamps(): void { if ($this->createdAt === null) { $this->createdAt = new \DateTimeImmutable(); } $this->updatedAt = new \DateTimeImmutable(); } } $anonymous = new class( $dependency ) { public function __construct(private mixed $dep) {} public function execute(): void { echo 'Anonymous class method'; } }; function helperFunction(string $input): string { return strtoupper($input); }
💖 Support This Project
Love this tool? Help me keep building awesome open source software!
Your sponsorship helps me dedicate more time to maintaining and improving this project. Every contribution, no matter the size, makes a difference!
🤝 Contributing
I welcome contributions! Whether it's a bug fix, new feature, or documentation improvement, I'd love to see your PRs.
📄 License
MIT License – Free to use in your projects! If you're using this and finding value, please consider sponsoring to support continued development.
ruudk/code-generator 适用场景与选型建议
ruudk/code-generator 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 202.28k 次下载、GitHub Stars 达 5, 最近一次更新时间为 2025 年 08 月 08 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「code generator」 「dev」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 ruudk/code-generator 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 ruudk/code-generator 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 ruudk/code-generator 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Memio's PrettyPrinter, used to generate PHP code from given Model
Monolog bridge for PHP Debugbar
Simple and fast methods to read private properties and call private methods
Analysis module for finding problematical shop data.
Analysis module for finding problematical shop data.
Enforce architecture by defining modules with allowed dependencies. Detects forbidden, uncovered, missing and unused module dependencies in PHP projects.
统计信息
- 总下载量: 202.28k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 5
- 点击次数: 30
- 依赖项目数: 2
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-08-08