jms/cg
jms/cg is a PHP code generation library that builds classes, methods, and properties programmatically. It provides a fluent API plus reflection and metadata support to generate readable source code, useful for proxies, serializers, and other build-time tooling.
Installation:
composer require jms/cg
First Use Case: Generate a simple PHP class dynamically.
use JMS\GeneratorBundle\Generator\Generator;
use JMS\GeneratorBundle\Generator\PhpClassGenerator;
use JMS\GeneratorBundle\Generator\PhpFile;
$class = new PhpClassGenerator('MyClass', 'MyNamespace');
$class->addMethod('getName', [], 'return "Test";');
$file = new PhpFile($class);
$file->setClass($class);
$generator = new Generator();
$generator->generate([$file], __DIR__.'/generated');
MyNamespace/MyClass.php in the generated directory.Key Classes to Explore:
PhpClassGenerator: For class structure.PhpMethodGenerator: For methods.PhpPropertyGenerator: For properties.PhpFile: For file-level configuration.$class = new PhpClassGenerator('User', 'App\\Models');
$class->setImplements(['Serializable']);
$class->addProperty('name', 'string')->setVisibility('private');
$class->addMethod('serialize', [], 'return $this->name;');
JMS\GeneratorBundle\Generator\TemplateType for reusable templates.$template = new TemplateType('path/to/template.twig');
$generator = new Generator();
$generator->generateFromTemplate($template, ['name' => 'User'], __DIR__.'/generated');
// In a Service Provider's boot method
$generator = app(Generator::class);
$generator->generate([$file], storage_path('app/generated'));
$files = [];
foreach ($entities as $entity) {
$class = new PhpClassGenerator($entity['name'], $entity['namespace']);
// ... configure class ...
$files[] = new PhpFile($class);
}
$generator->generate($files, __DIR__.'/generated');
$file = new PhpFile($class);
$file->setDirectory('Custom/Directory');
$file->setTargetFile('CustomName.php');
php artisan vendor:publish --provider="JMS\GeneratorBundle\JMSGeneratorBundle"
Generator in AppServiceProvider:
$this->app->bind(Generator::class, function ($app) {
return new Generator();
});
JMS\GeneratorBundle\Command\GenerateCommand for CLI tools.TemplateType.Generator::generate() with an array of PhpFile objects for efficiency.Generator in tests to avoid filesystem I/O:
$mockGenerator = $this->createMock(Generator::class);
$mockGenerator->method('generate')->willReturn(true);
PHP 7+ Compatibility:
use statements) may need manual adjustments.PhpClassGenerator::setUses() to explicitly declare dependencies.Namespace Collisions:
Template Caching:
$template = new TemplateType('template.twig', [], [], ['cache' => sys_get_temp_dir()]);
Visibility Defaults:
public. Omit setVisibility() to retain defaults.->setVisibility('private')).File Permissions:
storage_path() or a dedicated generated/ directory outside public/.Deprecated Methods:
addMethod()) may be deprecated in newer versions.addMethodWithBody().Verify Output:
php -l to lint:
php -l /path/to/generated/file.php
Enable Debug Mode:
JMS_GENERATOR_DEBUG=1 in your environment to log generation steps.Inspect Generators:
var_dump($class->generate()) to see raw PHP code before writing to disk.Template Errors:
{# template.twig #}
{% set strict_variables = true %}
Custom Generators:
JMS\GeneratorBundle\Generator\AbstractGenerator for domain-specific logic.class MyCustomGenerator extends AbstractGenerator {
protected function generateClass(PhpClassGenerator $class) {
// Add custom logic (e.g., annotations, traits)
$class->addTrait('MyCustomTrait');
return parent::generateClass($class);
}
}
Template Overrides:
resources/views/jms_generator/ or publish them:
php artisan vendor:publish --tag=jms-generator-templates
Event Listeners:
jms.generator.pre_generate and jms.generator.post_generate events (if using Symfony’s event system).Annotation Support:
doctrine/annotations to parse generated classes for metadata:use Doctrine\Common\Annotations\AnnotationReader;
$reader = new AnnotationReader();
$reflection = new ReflectionClass($generatedClass);
$annotations = $reader->getClassAnnotations($reflection);
IDE Integration:
// @generated comments to hint IDEs (e.g., PhpStorm) to ignore these files in "Open File" dialogs:$class->addComment('// @generated');
How can I help you explore Laravel packages today?