Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Twig Generator Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to Begin

  1. Installation:

    composer require cedriclombardot/twig-generator
    

    Ensure twig/twig and symfony/class-loader are also installed (handled automatically via Composer).

  2. First Use Case: Generate a simple PHP class with a method.

    • Create a Builder class extending TwigGenerator\Builder\BaseBuilder:
      namespace App\Builders;
      use TwigGenerator\Builder\BaseBuilder;
      
      class UserBuilder extends BaseBuilder {}
      
    • Create a Twig template (resources/templates/UserBuilder.twig):
      {% extends "_base/common.php.twig" %}
      {% block functions %}
          public function getName()
          {
              return "User";
          }
      {% endblock %}
      
    • Generate the class:
      $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');
      

Implementation Patterns

Workflows

  1. Template-Driven Generation:

    • Use base templates (e.g., _base/common.php.twig) for shared structures (namespaces, class declarations).
    • Extend base templates with feature-specific templates (e.g., methods, properties, traits).
    • Example:
      {# templates/EntityBuilder.twig #}
      {% extends "_base/common.php.twig" %}
      {% block properties %}
          private $id;
      {% endblock %}
      
  2. Dynamic Variable Injection:

    • Pass variables to templates via setVariables() on the Generator or Builder.
    • Example:
      $builder->setVariable('className', 'UserEntity');
      $generator->setVariables(['author' => 'John Doe']);
      
  3. Conditional Logic in Templates:

    • Use Twig’s if/for to conditionally generate code:
      {% if hasMethods %}
          {% for method in methods %}
              public function {{ method.name }}() {{{ method.body }}}
          {% endfor %}
      {% endif %}
      
  4. Reusable Builders:

    • Extend BaseBuilder for domain-specific logic (e.g., ModelBuilder, ServiceBuilder).
    • Override getTemplate() to dynamically select templates:
      class ModelBuilder extends BaseBuilder {
          public function getTemplate() {
              return 'models/' . $this->getOutputName() . '.twig';
          }
      }
      
  5. Integration with Laravel:

    • Service Providers: Register the generator as a singleton:
      $this->app->singleton('generator', function () {
          $generator = new \TwigGenerator\Builder\Generator();
          $generator->setTemplateDirs([base_path('resources/templates')]);
          return $generator;
      });
      
    • Artisan Commands: Create a custom command to trigger generation:
      php artisan generate:models --path=app/Models
      
  6. Caching:

    • Disable caching during development (setMustOverwriteIfExists(true)).
    • Enable caching in production for performance:
      $generator->setCacheDir(storage_path('framework/cache/generator'));
      

Gotchas and Tips

Pitfalls

  1. Template Inheritance:

    • Forgetting to {% extends %} a base template will break rendering.
    • Fix: Always chain templates (e.g., common.php.twigUserBuilder.twig).
  2. Variable Scope:

    • Variables set on the Generator override those on the Builder.
    • Tip: Use Builder-level variables for per-class configurations.
  3. Output Paths:

    • writeOnDisk() creates directories recursively, but permissions may fail.
    • Fix: Ensure the target directory is writable (e.g., chmod -R 775 Generated).
  4. Twig Syntax in PHP:

    • Unescaped output ({{{ variable }}}) can lead to XSS if variables contain user input.
    • Tip: Sanitize dynamic values before passing to templates.
  5. Namespace Conflicts:

    • Generated classes may clash with existing ones.
    • Fix: Use unique namespaces (e.g., App\Generated\Models).
  6. Template Loading:

    • Twig templates must be in a directory listed in setTemplateDirs().
    • Debug: Check TwigGenerator\Builder\Generator logs for missing template errors.

Debugging

  • Enable Twig Debug Mode:
    $generator->setDebug(true); // Shows template errors in detail.
    
  • Log Generated Output: Temporarily redirect output to a file:
    $generator->setOutputFile('debug_output.txt');
    

Extension Points

  1. Custom Builders:

    • Implement BuilderInterface for non-BaseBuilder logic:
      class CustomBuilder implements BuilderInterface {
          public function getTemplate() { ... }
          public function generate() { ... }
      }
      
  2. Pre/Post-Generation Hooks:

    • Extend Generator to add logic before/after writing files:
      $generator->addPostWriteHook(function ($filePath) {
          // Minify or lint the generated file.
      });
      
  3. Dynamic Template Selection:

    • Use getTemplate() to fetch templates from a database or API:
      public function getTemplate() {
          return $this->fetchTemplateFromDB($this->getOutputName());
      }
      
  4. Laravel Integration:

    • Publish templates via a package:
      // In ServiceProvider
      $this->publishes([
          __DIR__.'/templates' => resource_path('templates/generator'),
      ]);
      
    • Use Blade templates as Twig templates by converting them (e.g., with laravel-blade-to-twig).
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
bugban/symfony
beyonder-capi/workflow-extensions-bundle
beyonder-capi/job-queue-bundle
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin