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:
Fabien Potencier 2013-05-06 08:21:51 +02:00
commit 87cc7dc2a8
5 changed files with 65 additions and 26 deletions

View File

@ -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;
}
/**

View File

@ -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
}

View File

@ -33,6 +33,9 @@ class ProjectServiceContainer extends Container
$this->scopes = array();
$this->scopeChildren = array();
$this->methodMap = array(
'test' => 'getTestService',
);
}
/**

View File

@ -31,6 +31,9 @@ class ProjectServiceContainer extends Container
$this->scopes = array();
$this->scopeChildren = array();
$this->methodMap = array(
'foo' => 'getFooService',
);
}
/**

View File

@ -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',
);
}
/**