symplify/php-config-printer
Print Symfony service and parameter configs to clean PHP files using nikic/php-parser. Generate output for configured services only or full configs (e.g., from YAML arrays) via SmartPhpConfigPrinter and YamlToPhpConverter. Ideal for config transformations and automation.
Installation:
composer require symplify/php-config-printer --dev
Add to composer.json under require-dev to avoid runtime overhead.
First Use Case: Convert a Symfony-style service array to PHP for debugging:
use Symplify\PhpConfigPrinter\Printer\SmartPhpConfigPrinter;
$config = [
'App\Service\ExampleService' => [
'arguments' => ['$param' => 'value'],
'tags' => ['app.some_tag'],
],
];
$printer = new SmartPhpConfigPrinter();
$phpCode = $printer->printConfiguredServices($config);
file_put_contents('debug/services.php', $phpCode);
Output: A readable PHP file with the service definition.
Where to Look First:
Printer/SmartPhpConfigPrinter.php: Core class for converting configs to PHP.ValueObject/PhpConfigPrinterConfig.php: Configuration options (e.g., file paths, formatting).Converter/YamlToPhpConverter.php: For converting YAML configs (e.g., from services.yaml).Debugging Symfony Configs:
// Dump all configured services to a file
$printer->printConfiguredServices($container->getServiceDefinitions());
Useful for CI/CD pipelines or local development to inspect service definitions.
YAML-to-PHP Conversion:
$yaml = file_get_contents('config/services.yaml');
$converter = new YamlToPhpConverter();
$phpConfig = $converter->convertYamlString($yaml);
Ideal for teams migrating from YAML to PHP configs or sharing configs with non-Symfony teams.
Integration with Artisan: Create a custom command to generate PHP configs:
use Illuminate\Console\Command;
use Symplify\PhpConfigPrinter\Printer\SmartPhpConfigPrinter;
class GenerateConfigCommand extends Command
{
protected $signature = 'config:generate';
protected $description = 'Generate PHP configs from Symfony services';
public function handle(SmartPhpConfigPrinter $printer)
{
$config = $this->laravel['container']->getServiceDefinitions();
$phpCode = $printer->printConfiguredServices($config);
file_put_contents('storage/config.php', $phpCode);
$this->info('Config generated!');
}
}
Partial Configs: Target specific services:
$partialConfig = [
'App\Service\ApiClient' => [...],
];
$printer->printConfiguredServices($partialConfig);
CI/CD Pipeline:
# .github/workflows/validate-config.yml
- name: Generate PHP Configs
run: php artisan config:generate
- name: Validate PHP
run: php -l storage/config.php
Onboarding:
services.yaml to PHP for new developers:
vendor/bin/php-config-printer config/services.yaml > config/services.php
Tooling Integration:
Laravel-Specific Adaptations:
$services = $printer->printConfiguredServices($config);
$services = preg_replace('/tags.*/', 'tags: [\'app\']', $services); // Example
bind()/singleton() methods manually after conversion.Performance:
if (!file_exists('storage/config.php') || filemtime('config/services.yaml') > filemtime('storage/config.php')) {
$phpCode = $printer->printConfiguredServices($config);
file_put_contents('storage/config.php', $phpCode);
}
Testing:
$testConfig = ['App\Service\TestService' => [...]];
$phpCode = $printer->printConfiguredServices($testConfig);
$this->assertStringContainsString('TestService', $phpCode);
Symfony Dependency:
DependencyInjection component, which may bloat your project if unused elsewhere.YAML Parsing Quirks:
Debug\Dumper\CliDumper first:
php bin/console debug:container --dump
Laravel Incompatibility:
ContainerConfigurator and services.yaml structure don’t map directly to Laravel.PHP Version:
File Overwriting:
printConfiguredServices() outputs raw PHP code; ensure target files are writable.Invalid Configs:
when conditions, factory services).nikic/php-parser directly to isolate the issue:
use PhpParser\ParserFactory;
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
$parser->parse(file_get_contents('services.yaml'));
Output Mismatches:
diff:
diff <(php artisan config:generate) expected.php
Memory Limits:
memory_limit or parse incrementally.Default Values:
_defaults section (e.g., autowire: true) won’t appear in the output unless explicitly defined.$config = array_merge_recursive([
'_defaults' => ['autowire' => true],
], $config);
File Paths:
PhpConfigPrinterConfig::FILE_PATH defaults to config/php-config-printer.php. Override in services.yaml:
services:
_defaults:
autowire: true
symplify.php_config_printer:
file_path: '%kernel.project_dir%/config/printed.php'
Custom Printers:
Extend SmartPhpConfigPrinter to add Laravel-specific formatting:
class LaravelPhpConfigPrinter extends SmartPhpConfigPrinter
{
protected function formatService(array $service): string
{
$formatted = parent::formatService($service);
// Add Laravel-specific logic (e.g., convert tags to Laravel format)
return $formatted;
}
}
Pre/Post-Processing: Hook into the conversion pipeline:
$converter = new YamlToPhpConverter();
$phpConfig = $converter->convertYamlString($yaml);
// Modify $phpConfig before printing
$printer->printConfiguredServices($phpConfig);
Artisan Commands: Create reusable commands for common tasks:
// app/Console/Commands/ExportConfigs.php
class ExportConfigs extends Command
{
public function handle()
{
$configs = [
'services' => $this->laravel['container']->getServiceDefinitions(),
'parameters' => $this->laravel['config']->all(),
];
foreach ($configs as $name => $config) {
file_put_contents("storage/{$name}.php", var_export($config, true));
}
}
}
How can I help you explore Laravel packages today?