cedriclombardot/twig-generator
TwigGenerator is a PHP code generator powered by Twig templates. Create builders and reusable template layouts to generate PHP classes and features cleanly and extensibly, using a Generator to render templates into output files.
Installation:
composer require cedriclombardot/twig-generator
Ensure twig/twig and symfony/class-loader are also installed (handled automatically via Composer).
First Use Case: Generate a simple PHP class with a method.
Builder class extending TwigGenerator\Builder\BaseBuilder:
namespace App\Builders;
use TwigGenerator\Builder\BaseBuilder;
class UserBuilder extends BaseBuilder {}
resources/templates/UserBuilder.twig):
{% extends "_base/common.php.twig" %}
{% block functions %}
public function getName()
{
return "User";
}
{% endblock %}
$builder = new UserBuilder();
$builder->setOutputName('User.php');
$generator = new \TwigGenerator\Builder\Generator();
$generator->setTemplateDirs([__DIR__.'/resources/templates']);
$generator->setVariables(['namespace' => 'App\Generated']);
$generator->addBuilder($builder);
$generator->writeOnDisk(__DIR__.'/Generated');
Template-Driven Generation:
_base/common.php.twig) for shared structures (namespaces, class declarations).{# templates/EntityBuilder.twig #}
{% extends "_base/common.php.twig" %}
{% block properties %}
private $id;
{% endblock %}
Dynamic Variable Injection:
setVariables() on the Generator or Builder.$builder->setVariable('className', 'UserEntity');
$generator->setVariables(['author' => 'John Doe']);
Conditional Logic in Templates:
if/for to conditionally generate code:
{% if hasMethods %}
{% for method in methods %}
public function {{ method.name }}() {{{ method.body }}}
{% endfor %}
{% endif %}
Reusable Builders:
BaseBuilder for domain-specific logic (e.g., ModelBuilder, ServiceBuilder).getTemplate() to dynamically select templates:
class ModelBuilder extends BaseBuilder {
public function getTemplate() {
return 'models/' . $this->getOutputName() . '.twig';
}
}
Integration with Laravel:
$this->app->singleton('generator', function () {
$generator = new \TwigGenerator\Builder\Generator();
$generator->setTemplateDirs([base_path('resources/templates')]);
return $generator;
});
php artisan generate:models --path=app/Models
Caching:
setMustOverwriteIfExists(true)).$generator->setCacheDir(storage_path('framework/cache/generator'));
Template Inheritance:
{% extends %} a base template will break rendering.common.php.twig → UserBuilder.twig).Variable Scope:
Generator override those on the Builder.Builder-level variables for per-class configurations.Output Paths:
writeOnDisk() creates directories recursively, but permissions may fail.chmod -R 775 Generated).Twig Syntax in PHP:
{{{ variable }}}) can lead to XSS if variables contain user input.Namespace Conflicts:
App\Generated\Models).Template Loading:
setTemplateDirs().TwigGenerator\Builder\Generator logs for missing template errors.$generator->setDebug(true); // Shows template errors in detail.
$generator->setOutputFile('debug_output.txt');
Custom Builders:
BuilderInterface for non-BaseBuilder logic:
class CustomBuilder implements BuilderInterface {
public function getTemplate() { ... }
public function generate() { ... }
}
Pre/Post-Generation Hooks:
Generator to add logic before/after writing files:
$generator->addPostWriteHook(function ($filePath) {
// Minify or lint the generated file.
});
Dynamic Template Selection:
getTemplate() to fetch templates from a database or API:
public function getTemplate() {
return $this->fetchTemplateFromDB($this->getOutputName());
}
Laravel Integration:
// In ServiceProvider
$this->publishes([
__DIR__.'/templates' => resource_path('templates/generator'),
]);
laravel-blade-to-twig).How can I help you explore Laravel packages today?