Skip to content

Instantly share code, notes, and snippets.

@madmis
Created January 13, 2017 08:26
Show Gist options
  • Save madmis/136c11fca22433f7d5ed476de7b44de5 to your computer and use it in GitHub Desktop.
Save madmis/136c11fca22433f7d5ed476de7b44de5 to your computer and use it in GitHub Desktop.
Symfony services dependencies tree
#!/usr/bin/env php
<?php
set_time_limit(0);
require_once __DIR__.'/bootstrap.php.cache';
require_once __DIR__.'/AppKernel.php';
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
class DumperKernel extends AppKernel
{
/**
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
*/
private $builder;
/**
* @var array
*/
private $parameters;
/**
* @var \Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraph
*/
private $graph;
/**
* @var int
*/
private $maxLevel;
/**
* @var bool
*/
private $details = false;
/**
* @var bool
*/
private $initialized = false;
public function initialize()
{
$this->initializeBundles();
$this->initializeContainer();
$this->parameters = $this->builder->getParameterBag()->all();
$this->graph = $this->builder->getCompiler()->getServiceReferenceGraph();
$this->initialized = true;
}
/**
* Initializes the service container.
*/
protected function initializeContainer()
{
$container = $this->buildContainer();
$container->compile();
$this->builder = $container;
}
/**
* @param string $serviceId
* @param ConsoleOutput $output
*/
protected function describeService($serviceId, ConsoleOutput $output, $level = 0)
{
if ($level > $this->maxLevel) {
return;
}
$node = $this->graph->getNode($serviceId);
/** @var \Symfony\Component\DependencyInjection\Definition $value */
$value = $node->getValue();
$args = $value->getArguments();
$class = $value->getClass();
if (!$class || $class === 'stdClass') {
$fileName = '';
} else {
$reflector = new ReflectionClass($class);
$fileName = $reflector->getFileName();
}
$tab = str_repeat(" ", $level);
$output->writeln("{$tab}<comment>{$serviceId}</comment>");
if ($this->details) {
$output->writeln("{$tab}Class: {$class}");
$output->writeln("{$tab}File: {$fileName}");
$output->writeln("{$tab}Factory: {$value->getFactory()}, FactoryClass: {$value->getFactoryClass(false)}, FactoryMethod: {$value->getFactoryMethod(false)}, FactoryService: {$value->getFactoryService(false)}");
}
/** @var \Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphEdge[] $outEdges */
$outEdges = $node->getOutEdges();
if ($outEdges) {
foreach ($outEdges as $edge) {
/** @var \Symfony\Component\DependencyInjection\Reference $edgeNode */
$edgeNode = $edge->getValue();
$this->describeService((string) $edge->getValue(), $output, $level + 1);
}
}
}
public function dump(ArgvInput $input, ConsoleOutput $output)
{
if (!$this->initialized) {
$this->initialize();
}
$serviceId = $input->getArgument('service');
$this->maxLevel = $input->getOption('max-level');
$this->details = $input->getOption('details');
$this->describeService($serviceId, $output, 0);
}
}
$input = new ArgvInput();
$input->bind(
new InputDefinition(
[
new InputArgument('service', InputArgument::REQUIRED, 'A service name (app.foo)'),
new InputOption(
'max-level', null, InputOption::VALUE_REQUIRED, 'Set max nesting level', 9999
),
new InputOption(
'details', null, InputOption::VALUE_NONE, 'Show service details'
),
]
)
);
$output = new ConsoleOutput();
$env = $input->getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev');
$debug = !$input->hasParameterOption(['--no-debug', '']);
$kernel = new DumperKernel($env, true);
$kernel->dump($input, $output);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment