Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[DI] Generate one file per service factory #23678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/Symfony/Bridge/Doctrine/ManagerRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) {
if (isset($this->aliases[$name])) {
$name = $this->aliases[$name];
}
$method = $this->methodMap[$name] ?? 'get'.strtr($name, $this->underscoreMap).'Service'; // BC with DI v3.4
$wrappedInstance = $this->{$method}(false);
if (isset($this->fileMap[$name])) {
$wrappedInstance = $this->requireInScope($this->fileMap[$name], false);
} else { // BC with DI v3.4
$method = $this->methodMap[$name] ?? 'get'.strtr($name, $this->underscoreMap).'Service';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolas-grekas you said on Slack that you can submit it on 3.4 but that version AFAIS has php >=5.5.9 requirement, so ?? operator is not compatible. So it should be changed when submitting to 3.4 or maybe @$this->methodMap[$name] ?: should be used instead.

$wrappedInstance = $this->{$method}(false);
}

$manager->setProxyInitializer(null);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator;

use ProxyManager\Factory\LazyLoadingValueHolderFactory as BaseFactory;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\LazyLoadingValueHolderGenerator;

/**
* @internal
*/
class LazyLoadingValueHolderFactoryV1 extends BaseFactory
{
private $generatorV1;

/**
* {@inheritdoc}
*/
protected function getGenerator()
{
return $this->generatorV1 ?: $this->generatorV1 = new LazyLoadingValueHolderGenerator();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator;

use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;
use ProxyManager\Factory\LazyLoadingValueHolderFactory as BaseFactory;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\LazyLoadingValueHolderGenerator;

/**
* @internal
*/
class LazyLoadingValueHolderFactoryV2 extends BaseFactory
{
private $generator;

/**
* {@inheritdoc}
*/
protected function getGenerator(): ProxyGeneratorInterface
{
return $this->generator ?: $this->generator = new LazyLoadingValueHolderGenerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ public function __construct()
$config = new Configuration();
$config->setGeneratorStrategy(new EvaluatingGeneratorStrategy());

$this->factory = new LazyLoadingValueHolderFactory($config);
if (method_exists('ProxyManager\Version', 'getVersion')) {
$this->factory = new LazyLoadingValueHolderFactoryV2($config);
} else {
$this->factory = new LazyLoadingValueHolderFactoryV1($config);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper;

use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator as BaseGenerator;
use Zend\Code\Generator\ClassGenerator;

/**
* @internal
*/
class LazyLoadingValueHolderGenerator extends BaseGenerator
{
/**
* {@inheritdoc}
*/
public function generate(\ReflectionClass $originalClass, ClassGenerator $classGenerator)
{
parent::generate($originalClass, $classGenerator);

if ($classGenerator->hasMethod('__destruct')) {
$destructor = $classGenerator->getMethod('__destruct');
$body = $destructor->getBody();
$newBody = preg_replace('/^(\$this->initializer[\d\w]++) && .*;\n\nreturn (\$this->valueHolder)/', '$1 || $2', $body);

if ($body === $newBody) {
throw new \UnexpectedValueException(sprintf('Unexpected lazy-proxy format generated for method %s::__destruct()', $originalClass->name));
}

$destructor->setBody($newBody);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

use ProxyManager\Generator\ClassGenerator;
use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy;
use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface;
Expand Down Expand Up @@ -70,7 +69,12 @@ public function getProxyFactoryCode(Definition $definition, $id, $factoryCode =
$instantiation = 'return';

if ($definition->isShared()) {
$instantiation .= sprintf(' $this->%s[\'%s\'] =', $definition->isPublic() || !method_exists(ContainerBuilder::class, 'addClassResource') ? 'services' : 'privates', $id);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice idiom refactor:smile:

if (!method_exists(ContainerBuilder::class, 'addClassResource')) {
$instantiation .= sprintf(' $this->%s[\'%s\'] =', $definition->isPublic() ? 'services' : 'privates', $id);
} else {
// BC with DI v3.4
$instantiation .= sprintf(' $this->services[\'%s\'] =', $id);
}
}

if (null === $factoryCode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public function testCreateProxyServiceWithRuntimeInstantiator()
/* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */
$foo1 = $builder->get('foo1');

$foo1->__destruct();
$this->assertSame(0, $foo1::$destructorCount);

$this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls');
$this->assertInstanceOf('\ProxyManagerBridgeFooClass', $foo1);
$this->assertInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1);
Expand All @@ -50,5 +53,8 @@ public function testCreateProxyServiceWithRuntimeInstantiator()
$this->assertTrue($foo1->isProxyInitialized());
$this->assertInstanceOf('\ProxyManagerBridgeFooClass', $foo1->getWrappedValueHolderValue());
$this->assertNotInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1->getWrappedValueHolderValue());

$foo1->__destruct();
$this->assertSame(1, $foo1::$destructorCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

class ProxyManagerBridgeFooClass
{
public static $destructorCount = 0;

public $foo;
public $moo;

Expand Down Expand Up @@ -38,4 +40,9 @@ public function setBar($value = null)
{
$this->bar = $value;
}

public function __destruct()
{
++self::$destructorCount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use Symfony\Component\Console\Style\SymfonyStyle;

/**
* Clear and Warmup the cache.
* Clear the cache.
*
* @author Francis Besset <[email protected]>
* @author Fabien Potencier <[email protected]>
Expand Down
68 changes: 34 additions & 34 deletions src/Symfony/Component/DependencyInjection/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Container implements ResettableContainerInterface
protected $parameterBag;

protected $services = array();
protected $fileMap = array();
protected $methodMap = array();
protected $aliases = array();
protected $loading = array();
Expand Down Expand Up @@ -150,7 +151,7 @@ public function set($id, $service)
throw new InvalidArgumentException('You cannot set service "service_container".');
}

if (isset($this->methodMap[$id])) {
if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
throw new InvalidArgumentException(sprintf('You cannot set the pre-defined service "%s".', $id));
}

Expand Down Expand Up @@ -186,19 +187,12 @@ public function has($id)
return true;
}

if (isset($this->methodMap[$id])) {
return true;
}

return false;
return isset($this->fileMap[$id]) || isset($this->methodMap[$id]);
}

/**
* Gets a service.
*
* If a service is defined both through a set() method and
* with a get{$id}Service() method, the former has always precedence.
*
* @param string $id The service identifier
* @param int $invalidBehavior The behavior when the service does not exist
*
Expand Down Expand Up @@ -228,32 +222,14 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE
throw new ServiceCircularReferenceException($id, array_keys($this->loading));
}

if (isset($this->methodMap[$id])) {
$method = $this->methodMap[$id];
} else {
if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
if (!$id) {
throw new ServiceNotFoundException($id);
}

$alternatives = array();
foreach ($this->getServiceIds() as $knownId) {
$lev = levenshtein($id, $knownId);
if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) {
$alternatives[] = $knownId;
}
}

throw new ServiceNotFoundException($id, null, null, $alternatives);
}

return;
}

$this->loading[$id] = true;

try {
$service = $this->$method();
if (isset($this->fileMap[$id])) {
return $this->requireInScope($this->fileMap[$id]);
} elseif (isset($this->methodMap[$id])) {
return $this->{$this->methodMap[$id]}();
}
} catch (\Exception $e) {
unset($this->services[$id]);

Expand All @@ -262,7 +238,21 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE
unset($this->loading[$id]);
}

return $service;
if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) {
if (!$id) {
throw new ServiceNotFoundException($id);
}

$alternatives = array();
foreach ($this->getServiceIds() as $knownId) {
$lev = levenshtein($id, $knownId);
if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) {
$alternatives[] = $knownId;
}
}

throw new ServiceNotFoundException($id, null, null, $alternatives);
}
}

/**
Expand Down Expand Up @@ -300,7 +290,7 @@ public function reset()
*/
public function getServiceIds()
{
return array_unique(array_merge(array('service_container'), array_keys($this->methodMap), array_keys($this->services)));
return array_unique(array_merge(array('service_container'), array_keys($this->fileMap), array_keys($this->methodMap), array_keys($this->services)));
}

/**
Expand All @@ -327,6 +317,16 @@ public static function underscore($id)
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id)));
}

/**
* Creates a service by requiring its factory file.
*
* @return object The service created by the file
*/
protected function requireInScope($file)
{
return require $file;
}

/**
* Fetches a variable from the environment.
*
Expand Down
Loading