Procházet zdrojové kódy

[DependencyInjection] optimized compiled containers

 * removed the __call() method in Container: it means that now, there is only
   one way to get a service: via the get() method;

 * removed the $shared variable in the dumped Container classes (we now use
   the $services variable from the parent class directly -- this is where we
   have a performance improvement);

 * optimized the PHP Dumper output.
Fabien Potencier před 14 roky
rodič
revize
60bbb8f380
21 změnil soubory, kde provedl 41 přidání a 123 odebrání
  1. 2 2
      src/Symfony/Bundle/DoctrineBundle/Command/ConvertDoctrine1SchemaDoctrineCommand.php
  2. 1 1
      src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php
  3. 1 1
      src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php
  4. 1 1
      src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntityDoctrineCommand.php
  5. 2 2
      src/Symfony/Bundle/DoctrineBundle/Command/ImportMappingDoctrineCommand.php
  6. 2 2
      src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php
  7. 2 2
      src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php
  8. 1 1
      src/Symfony/Bundle/FrameworkBundle/Client.php
  9. 1 1
      src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
  10. 1 1
      src/Symfony/Bundle/FrameworkBundle/Command/InitBundleCommand.php
  11. 7 7
      src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
  12. 1 1
      src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php
  13. 1 22
      src/Symfony/Component/DependencyInjection/Container.php
  14. 11 23
      src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
  15. 1 1
      src/Symfony/Component/HttpKernel/Kernel.php
  16. 0 25
      tests/Symfony/Tests/Component/DependencyInjection/ContainerTest.php
  17. 1 2
      tests/Symfony/Tests/Component/DependencyInjection/Dumper/PhpDumperTest.php
  18. 0 2
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services1-1.php
  19. 0 2
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services1.php
  20. 0 2
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services8.php
  21. 5 22
      tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services9.php

+ 2 - 2
src/Symfony/Bundle/DoctrineBundle/Command/ConvertDoctrine1SchemaDoctrineCommand.php

@@ -56,8 +56,8 @@ EOT
     protected function execute(InputInterface $input, OutputInterface $output)
     {
         $bundleClass = null;
-        $bundleDirs = $this->container->getKernelService()->getBundleDirs();
-        foreach ($this->container->getKernelService()->getBundles() as $bundle) {
+        $bundleDirs = $this->container->get('kernel')->getBundleDirs();
+        foreach ($this->container->get('kernel')->getBundles() as $bundle) {
             if (strpos(get_class($bundle), $input->getArgument('bundle')) !== false) {
                 $tmp = dirname(str_replace('\\', '/', get_class($bundle)));
                 $namespace = str_replace('/', '\\', dirname($tmp));

+ 1 - 1
src/Symfony/Bundle/DoctrineBundle/Command/DoctrineCommand.php

@@ -88,7 +88,7 @@ abstract class DoctrineCommand extends Command
 
     protected function runCommand($name, array $input = array())
     {
-        $application = new Application($this->container->getKernelService());
+        $application = new Application($this->container->get('kernel'));
         $arguments = array();
         $arguments = array_merge(array($name), $input);
         $input = new ArrayInput($arguments);

+ 1 - 1
src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntitiesDoctrineCommand.php

@@ -62,7 +62,7 @@ EOT
         }
 
         $entityGenerator = $this->getEntityGenerator();
-        foreach ($this->container->getKernelService()->getBundles() as $bundle) {
+        foreach ($this->container->get('kernel')->getBundles() as $bundle) {
 
             // retrieve the full bundle classname
             $class = $bundle->getReflection()->getName();

+ 1 - 1
src/Symfony/Bundle/DoctrineBundle/Command/GenerateEntityDoctrineCommand.php

@@ -60,7 +60,7 @@ EOT
             throw new \InvalidArgumentException('The bundle name must end with Bundle. Example: "Bundle\MySampleBundle".');
         }
 
-        $dirs = $this->container->getKernelService()->getBundleDirs();
+        $dirs = $this->container->get('kernel')->getBundleDirs();
 
         $tmp = str_replace('\\', '/', $bundle);
         $namespace = str_replace('/', '\\', dirname($tmp));

+ 2 - 2
src/Symfony/Bundle/DoctrineBundle/Command/ImportMappingDoctrineCommand.php

@@ -54,8 +54,8 @@ EOT
     protected function execute(InputInterface $input, OutputInterface $output)
     {
         $bundleClass = null;
-        $bundleDirs = $this->container->getKernelService()->getBundleDirs();
-        foreach ($this->container->getKernelService()->getBundles() as $bundle) {
+        $bundleDirs = $this->container->get('kernel')->getBundleDirs();
+        foreach ($this->container->get('kernel')->getBundles() as $bundle) {
             if (strpos(get_class($bundle), $input->getArgument('bundle')) !== false) {
                 $tmp = dirname(str_replace('\\', '/', get_class($bundle)));
                 $namespace = str_replace('/', '\\', dirname($tmp));

+ 2 - 2
src/Symfony/Bundle/DoctrineBundle/Command/LoadDataFixturesDoctrineCommand.php

@@ -67,8 +67,8 @@ EOT
             $paths = is_array($dirOrFile) ? $dirOrFile : array($dirOrFile);
         } else {
             $paths = array();
-            $bundleDirs = $this->container->getKernelService()->getBundleDirs();
-            foreach ($this->container->getKernelService()->getBundles() as $bundle) {
+            $bundleDirs = $this->container->get('kernel')->getBundleDirs();
+            foreach ($this->container->get('kernel')->getBundles() as $bundle) {
                 $tmp = dirname(str_replace('\\', '/', get_class($bundle)));
                 $namespace = str_replace('/', '\\', dirname($tmp));
                 $class = basename($tmp);

+ 2 - 2
src/Symfony/Bundle/DoctrineMongoDBBundle/Command/LoadDataFixturesDoctrineODMCommand.php

@@ -67,8 +67,8 @@ EOT
             $paths = is_array($dirOrFile) ? $dirOrFile : array($dirOrFile);
         } else {
             $paths = array();
-            $bundleDirs = $this->container->getKernelService()->getBundleDirs();
-            foreach ($this->container->getKernelService()->getBundles() as $bundle) {
+            $bundleDirs = $this->container->get('kernel')->getBundleDirs();
+            foreach ($this->container->get('kernel')->getBundles() as $bundle) {
                 $tmp = dirname(str_replace('\\', '/', get_class($bundle)));
                 $namespace = str_replace('/', '\\', dirname($tmp));
                 $class = basename($tmp);

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Client.php

@@ -75,7 +75,7 @@ class Client extends BaseClient
             return false;
         }
 
-        return $this->container->getProfilerService()->loadFromResponse($this->response);
+        return $this->container->get('profiler')->loadFromResponse($this->response);
     }
 
     /**

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php

@@ -52,7 +52,7 @@ class AssetsInstallCommand extends Command
 
         $filesystem = new Filesystem();
 
-        foreach ($this->container->getKernelService()->getBundles() as $bundle) {
+        foreach ($this->container->get('kernel')->getBundles() as $bundle) {
             if (is_dir($originDir = $bundle->getPath().'/Resources/public')) {
                 $output->writeln(sprintf('Installing assets for <comment>%s\\%s</comment>', $bundle->getNamespacePrefix(), $bundle->getName()));
 

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Command/InitBundleCommand.php

@@ -51,7 +51,7 @@ class InitBundleCommand extends Command
             throw new \InvalidArgumentException('The namespace must end with Bundle.');
         }
 
-        $dirs = $this->container->getKernelService()->getBundleDirs();
+        $dirs = $this->container->get('kernel')->getBundleDirs();
 
         $tmp = str_replace('\\', '/', $namespace);
         $namespace = str_replace('/', '\\', dirname($tmp));

+ 7 - 7
src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php

@@ -96,7 +96,7 @@ class ControllerResolver extends BaseControllerResolver
     public function forward($controller, array $attributes = array(), array $query = array())
     {
         $attributes['_controller'] = $controller;
-        $subRequest = $this->container->getRequestService()->duplicate($query, null, $attributes);
+        $subRequest = $this->container->get('request')->duplicate($query, null, $attributes);
 
         return $this->container->get('kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
     }
@@ -137,7 +137,7 @@ class ControllerResolver extends BaseControllerResolver
         }
 
         if (null === $this->esiSupport) {
-            $this->esiSupport = $this->container->has('esi') && $this->container->getEsiService()->hasSurrogateEsiCapability($this->container->getRequestService());
+            $this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($this->container->get('request'));
         }
 
         if ($this->esiSupport && $options['standalone']) {
@@ -148,10 +148,10 @@ class ControllerResolver extends BaseControllerResolver
                 $alt = $this->generateInternalUri($options['alt'][0], isset($options['alt'][1]) ? $options['alt'][1] : array(), isset($options['alt'][2]) ? $options['alt'][2] : array());
             }
 
-            return $this->container->getEsiService()->renderIncludeTag($uri, $alt, $options['ignore_errors'], $options['comment']);
+            return $this->container->get('esi')->renderIncludeTag($uri, $alt, $options['ignore_errors'], $options['comment']);
         }
 
-        $request = $this->container->getRequestService();
+        $request = $this->container->get('request');
 
         // controller or URI?
         if (0 === strpos($controller, '/')) {
@@ -164,7 +164,7 @@ class ControllerResolver extends BaseControllerResolver
         }
 
         try {
-            $response = $this->container->getKernelService()->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
+            $response = $this->container->get('kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
 
             if (200 != $response->getStatusCode()) {
                 throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $request->getUri(), $response->getStatusCode()));
@@ -204,10 +204,10 @@ class ControllerResolver extends BaseControllerResolver
             return $controller;
         }
 
-        $uri = $this->container->getRouterService()->generate('_internal', array(
+        $uri = $this->container->get('router')->generate('_internal', array(
             'controller' => $controller,
             'path'       => $attributes ? http_build_query($attributes) : 'none',
-            '_format'    => $this->container->getRequestService()->getRequestFormat(),
+            '_format'    => $this->container->get('request')->getRequestFormat(),
         ), true);
 
         if ($query) {

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Test/WebTestCase.php

@@ -39,7 +39,7 @@ abstract class WebTestCase extends BaseWebTestCase
         $this->kernel = $this->createKernel($options);
         $this->kernel->boot();
 
-        $client = $this->kernel->getContainer()->getTest_ClientService();
+        $client = $this->kernel->getContainer()->get('test.client');
         $client->setServerParameters($server);
 
         return $client;

+ 1 - 22
src/Symfony/Component/DependencyInjection/Container.php

@@ -181,9 +181,7 @@ class Container implements ContainerInterface
      */
     public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE)
     {
-        if (!is_string($id)) {
-            throw new \InvalidArgumentException(sprintf('A service id should be a string (%s given).', str_replace("\n", '', var_export($id, true))));
-        }
+        $id = (string) $id;
 
         if (isset($this->services[$id])) {
             return $this->services[$id];
@@ -216,25 +214,6 @@ class Container implements ContainerInterface
         return array_merge($ids, array_keys($this->services));
     }
 
-    /**
-     * Catches unknown methods.
-     *
-     * @param string $method    The called method name
-     * @param array  $arguments The method arguments
-     *
-     * @return mixed
-     *
-     * @throws \BadMethodCallException When calling to an undefined method
-     */
-    public function __call($method, $arguments)
-    {
-        if (!preg_match('/^get(.+)Service$/', $method, $match)) {
-            throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
-        }
-
-        return $this->get(self::underscore($match[1]));
-    }
-
     static public function camelize($id)
     {
         return preg_replace(array('/(?:^|_)+(.)/e', '/\.(.)/e'), array("strtoupper('\\1')", "'_'.strtoupper('\\1')"), $id);

+ 11 - 23
src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

@@ -60,17 +60,6 @@ class PhpDumper extends Dumper
         }
     }
 
-    protected function addServiceShared($id, $definition)
-    {
-        if ($definition->isShared()) {
-            return <<<EOF
-        if (isset(\$this->shared['$id'])) return \$this->shared['$id'];
-
-
-EOF;
-        }
-    }
-
     protected function addServiceReturn($id, $definition)
     {
         return <<<EOF
@@ -94,20 +83,22 @@ EOF;
             $arguments[] = $this->dumpValue($value);
         }
 
+        if ($definition->isShared()) {
+            $instantiation = sprintf("        \$this->services['$id'] = \$instance");
+        } else {
+            $instantiation = sprintf("        \$instance");
+        }
+
         if (null !== $definition->getFactoryMethod()) {
             if (null !== $definition->getFactoryService()) {
-                $code = sprintf("        \$instance = %s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments));
+                $code = sprintf("$instantiation = %s->%s(%s);\n", $this->getServiceCall($definition->getFactoryService()), $definition->getFactoryMethod(), implode(', ', $arguments));
             } else {
-                $code = sprintf("        \$instance = call_user_func(array(%s, '%s')%s);\n", $class, $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : '');
+                $code = sprintf("$instantiation = call_user_func(array(%s, '%s')%s);\n", $class, $definition->getFactoryMethod(), $arguments ? ', '.implode(', ', $arguments) : '');
             }
-        } elseif ($class != "'".str_replace('\\', '\\\\', $definition->getClass())."'") {
-            $code = sprintf("        \$class = %s;\n        \$instance = new \$class(%s);\n", $class, implode(', ', $arguments));
+        } elseif (false !== strpos($class, '$')) {
+            $code = sprintf("        \$class = %s;\n$instantiation = new \$class(%s);\n", $class, implode(', ', $arguments));
         } else {
-            $code = sprintf("        \$instance = new %s(%s);\n", $definition->getClass(), implode(', ', $arguments));
-        }
-
-        if ($definition->isShared()) {
-            $code .= sprintf("        \$this->shared['$id'] = \$instance;\n");
+            $code = sprintf("$instantiation = new \\%s(%s);\n", substr(str_replace('\\\\', '\\', $class), 1, -1), implode(', ', $arguments));
         }
 
         return $code;
@@ -180,7 +171,6 @@ EOF;
 
         $code .=
             $this->addServiceInclude($id, $definition).
-            $this->addServiceShared($id, $definition).
             $this->addServiceInstance($id, $definition).
             $this->addServiceMethodCalls($id, $definition).
             $this->addServiceConfigurator($id, $definition).
@@ -284,8 +274,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\\$bagClass;
  */
 class $class extends $baseClass implements TaggedContainerInterface
 {
-    protected \$shared = array();
-
 EOF;
     }
 

+ 1 - 1
src/Symfony/Component/HttpKernel/Kernel.php

@@ -178,7 +178,7 @@ abstract class Kernel implements HttpKernelInterface, \Serializable
             $this->boot();
         }
 
-        return $this->container->getHttpKernelService()->handle($request, $type, $catch);
+        return $this->container->get('http_kernel')->handle($request, $type, $catch);
     }
 
     /**

+ 0 - 25
tests/Symfony/Tests/Component/DependencyInjection/ContainerTest.php

@@ -99,24 +99,6 @@ class ContainerTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals(array('bar', 'foo_bar', 'foo.baz', 'service_container'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods');
     }
 
-    /**
-     * @covers Symfony\Component\DependencyInjection\Container::__call
-     */
-    public function testGetCall()
-    {
-        $sc = new Container();
-        $sc->set('foo_bar.foo', $foo = new \stdClass());
-        $this->assertEquals($foo, $sc->getFooBar_FooService(), '__call() finds services is the method is getXXXService()');
-
-        try {
-            $sc->getFooBar_Foo();
-            $this->fail('__call() throws a \BadMethodCallException exception if the method is not a service method');
-        } catch (\Exception $e) {
-            $this->assertInstanceOf('\BadMethodCallException', $e, '__call() throws a \BadMethodCallException exception if the method is not a service method');
-            $this->assertEquals('Call to undefined method Symfony\Component\DependencyInjection\Container::getFooBar_Foo.', $e->getMessage(), '__call() throws a \BadMethodCallException exception if the method is not a service method');
-        }
-    }
-
     /**
      * @covers Symfony\Component\DependencyInjection\Container::set
      */
@@ -142,13 +124,6 @@ class ContainerTest extends \PHPUnit_Framework_TestCase
         $sc->set('bar', $bar = new \stdClass());
         $this->assertSame($sc->get('bar'), $bar, '->getServiceIds() prefers to return a service defined with a getXXXService() method than one defined with set()');
 
-        try {
-            $sc->get(new \stdClass());
-            $this->fail('->get() throws a \InvalidArgumentException exception if the service id is not a string');
-        } catch (\Exception $e) {
-            $this->assertInstanceOf('\InvalidArgumentException', $e, '->get() throws a \InvalidArgumentException exception if the service id is not a string');
-        }
-
         try {
             $sc->get('');
             $this->fail('->get() throws a \InvalidArgumentException exception if the service is empty');

+ 1 - 2
tests/Symfony/Tests/Component/DependencyInjection/Dumper/PhpDumperTest.php

@@ -77,7 +77,6 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
         $container->set('bar', $bar = new \stdClass());
         $container->setParameter('foo_bar', 'foo_bar');
 
-        $this->assertEquals($bar, $container->getBarService(), '->set() overrides an already defined service');
         $this->assertEquals($bar, $container->get('bar'), '->set() overrides an already defined service');
     }
 
@@ -90,6 +89,6 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
         $container = new \ProjectServiceContainer();
         $container->set('bar', $bar = new \stdClass());
 
-        $this->assertSame($bar, $container->getFooService()->bar, '->set() overrides an already defined service');
+        $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service');
     }
 }

+ 0 - 2
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services1-1.php

@@ -15,8 +15,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  */
 class Container extends AbstractContainer implements TaggedContainerInterface
 {
-    protected $shared = array();
-
     /**
      * Constructor.
      */

+ 0 - 2
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services1.php

@@ -15,8 +15,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  */
 class ProjectServiceContainer extends Container implements TaggedContainerInterface
 {
-    protected $shared = array();
-
     /**
      * Constructor.
      */

+ 0 - 2
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services8.php

@@ -15,8 +15,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  */
 class ProjectServiceContainer extends Container implements TaggedContainerInterface
 {
-    protected $shared = array();
-
     /**
      * Constructor.
      */

+ 5 - 22
tests/Symfony/Tests/Component/DependencyInjection/Fixtures/php/services9.php

@@ -15,8 +15,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
  */
 class ProjectServiceContainer extends Container implements TaggedContainerInterface
 {
-    protected $shared = array();
-
     /**
      * Constructor.
      */
@@ -50,10 +48,7 @@ class ProjectServiceContainer extends Container implements TaggedContainerInterf
      */
     protected function getBarService()
     {
-        if (isset($this->shared['bar'])) return $this->shared['bar'];
-
-        $instance = new FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar'));
-        $this->shared['bar'] = $instance;
+        $this->services['bar'] = $instance = new \FooClass('foo', $this->get('foo.baz'), $this->getParameter('foo_bar'));
         $this->get('foo.baz')->configure($instance);
 
         return $instance;
@@ -69,10 +64,7 @@ class ProjectServiceContainer extends Container implements TaggedContainerInterf
      */
     protected function getFoo_BazService()
     {
-        if (isset($this->shared['foo.baz'])) return $this->shared['foo.baz'];
-
-        $instance = call_user_func(array($this->getParameter('baz_class'), 'getInstance'));
-        $this->shared['foo.baz'] = $instance;
+        $this->services['foo.baz'] = $instance = call_user_func(array($this->getParameter('baz_class'), 'getInstance'));
         call_user_func(array($this->getParameter('baz_class'), 'configureStatic1'), $instance);
 
         return $instance;
@@ -88,11 +80,8 @@ class ProjectServiceContainer extends Container implements TaggedContainerInterf
      */
     protected function getFooBarService()
     {
-        if (isset($this->shared['foo_bar'])) return $this->shared['foo_bar'];
-
         $class = $this->getParameter('foo_class');
-        $instance = new $class();
-        $this->shared['foo_bar'] = $instance;
+        $this->services['foo_bar'] = $instance = new $class();
 
         return $instance;
     }
@@ -109,10 +98,7 @@ class ProjectServiceContainer extends Container implements TaggedContainerInterf
     {
         require_once '%path%foo.php';
 
-        if (isset($this->shared['method_call1'])) return $this->shared['method_call1'];
-
-        $instance = new FooClass();
-        $this->shared['method_call1'] = $instance;
+        $this->services['method_call1'] = $instance = new \FooClass();
         $instance->setBar($this->get('foo'));
         $instance->setBar($this->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE));
         if ($this->has('foo')) {
@@ -135,10 +121,7 @@ class ProjectServiceContainer extends Container implements TaggedContainerInterf
      */
     protected function getFactoryServiceService()
     {
-        if (isset($this->shared['factory_service'])) return $this->shared['factory_service'];
-
-        $instance = $this->get('foo.baz')->getInstance();
-        $this->shared['factory_service'] = $instance;
+        $this->services['factory_service'] = $instance = $this->get('foo.baz')->getInstance();
 
         return $instance;
     }