merged branch Seldaek/methodmap (PR #7933)
This PR was merged into the master branch.
Discussion
----------
[DependencyInjection] Add a method map to avoid computing method names from service names
/cc @schmittjoh @stof
The diff is a bit messy because of indenting, but all this adds really is an `if(isset($this->methodMap[$id])) { $method = $this->methodMap[$id]; }` that bypasses the method_exists + strtr calls. It's not a huge improvements but saves some cycles on something that's typically called a few hundred times per request.
Commits
-------
f1c2ab7
[DependencyInjection] Add a method map to avoid computing method names from service names
This commit is contained in:
commit
87cc7dc2a8
@ -68,6 +68,7 @@ class Container implements IntrospectableContainerInterface
|
||||
protected $parameterBag;
|
||||
|
||||
protected $services;
|
||||
protected $methodMap;
|
||||
protected $scopes;
|
||||
protected $scopeChildren;
|
||||
protected $scopedServices;
|
||||
@ -260,45 +261,50 @@ class Container implements IntrospectableContainerInterface
|
||||
throw new ServiceCircularReferenceException($id, array_keys($this->loading));
|
||||
}
|
||||
|
||||
if (method_exists($this, $method = 'get'.strtr($id, array('_' => '', '.' => '_')).'Service')) {
|
||||
$this->loading[$id] = true;
|
||||
|
||||
try {
|
||||
$service = $this->$method();
|
||||
} catch (\Exception $e) {
|
||||
unset($this->loading[$id]);
|
||||
|
||||
if (array_key_exists($id, $this->services)) {
|
||||
unset($this->services[$id]);
|
||||
if (isset($this->methodMap[$id])) {
|
||||
$method = $this->methodMap[$id];
|
||||
} elseif (method_exists($this, $method = 'get'.strtr($id, array('_' => '', '.' => '_')).'Service')) {
|
||||
} else {
|
||||
if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
|
||||
if (!$id) {
|
||||
throw new ServiceNotFoundException($id);
|
||||
}
|
||||
|
||||
if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
|
||||
return null;
|
||||
$alternatives = array();
|
||||
foreach (array_keys($this->services) as $key) {
|
||||
$lev = levenshtein($id, $key);
|
||||
if ($lev <= strlen($id) / 3 || false !== strpos($key, $id)) {
|
||||
$alternatives[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
throw $e;
|
||||
throw new ServiceNotFoundException($id, null, null, $alternatives);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->loading[$id] = true;
|
||||
|
||||
try {
|
||||
$service = $this->$method();
|
||||
} catch (\Exception $e) {
|
||||
unset($this->loading[$id]);
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
|
||||
if (!$id) {
|
||||
throw new ServiceNotFoundException($id);
|
||||
if (array_key_exists($id, $this->services)) {
|
||||
unset($this->services[$id]);
|
||||
}
|
||||
|
||||
$alternatives = array();
|
||||
foreach (array_keys($this->services) as $key) {
|
||||
$lev = levenshtein($id, $key);
|
||||
if ($lev <= strlen($id) / 3 || false !== strpos($key, $id)) {
|
||||
$alternatives[] = $key;
|
||||
}
|
||||
if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new ServiceNotFoundException($id, null, null, $alternatives);
|
||||
throw $e;
|
||||
}
|
||||
|
||||
unset($this->loading[$id]);
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -779,6 +779,20 @@ EOF;
|
||||
$code .= " \$this->scopeChildren = array();\n";
|
||||
}
|
||||
|
||||
// build method map
|
||||
$code .= " \$this->methodMap = array(\n";
|
||||
$definitions = $this->container->getDefinitions();
|
||||
ksort($definitions);
|
||||
foreach ($definitions as $id => $definition) {
|
||||
$code .= ' '.var_export($id, true).' => '.var_export('get'.Container::camelize($id).'Service', true).",\n";
|
||||
}
|
||||
$aliases = $this->container->getAliases();
|
||||
ksort($aliases);
|
||||
foreach ($aliases as $alias => $id) {
|
||||
$code .= ' '.var_export($alias, true).' => '.var_export('get'.Container::camelize($id).'Service', true).",\n";
|
||||
}
|
||||
$code .= " );\n";
|
||||
|
||||
$code .= <<<EOF
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,9 @@ class ProjectServiceContainer extends Container
|
||||
|
||||
$this->scopes = array();
|
||||
$this->scopeChildren = array();
|
||||
$this->methodMap = array(
|
||||
'test' => 'getTestService',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,6 +31,9 @@ class ProjectServiceContainer extends Container
|
||||
|
||||
$this->scopes = array();
|
||||
$this->scopeChildren = array();
|
||||
$this->methodMap = array(
|
||||
'foo' => 'getFooService',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,6 +33,19 @@ class ProjectServiceContainer extends Container
|
||||
|
||||
$this->scopes = array();
|
||||
$this->scopeChildren = array();
|
||||
$this->methodMap = array(
|
||||
'bar' => 'getBarService',
|
||||
'baz' => 'getBazService',
|
||||
'depends_on_request' => 'getDependsOnRequestService',
|
||||
'factory_service' => 'getFactoryServiceService',
|
||||
'foo' => 'getFooService',
|
||||
'foo.baz' => 'getFoo_BazService',
|
||||
'foo_bar' => 'getFooBarService',
|
||||
'foo_with_inline' => 'getFooWithInlineService',
|
||||
'method_call1' => 'getMethodCall1Service',
|
||||
'request' => 'getRequestService',
|
||||
'alias_for_foo' => 'getFooService',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user