8000 Lazy services - service proxies by Ocramius · Pull Request #7527 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

Lazy services - service proxies #7527

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 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f503ad8
First implementation of lazy services via proxy manager
Ocramius Mar 29, 2013
67aef45
Adding basic logic to generate proxy instantiation into a php dumped …
Ocramius Mar 30, 2013
f4a19c7
Compiling proxies into the generated DIC file
Ocramius Mar 30, 2013
d2760f1
Upgrading dependency to ProxyManager 0.3.*
Ocramius Mar 30, 2013
4a13f82
Suggesting ProxyManager in composer.json, removing useless calls
Ocramius Mar 31, 2013
a6a6572
Adding failing test to demonstrate that proxy initialization breaks s…
Ocramius Mar 31, 2013
35fdded
Fixing shared service instance 8000
Ocramius Mar 31, 2013
bec7774
Sharing services in the container should only happen when proxying fa…
Ocramius Mar 31, 2013
468e92e
Adding tests for proxy sharing within dumped containers
Ocramius Mar 31, 2013
4ecd5ad
Fixing shared proxies into the container
Ocramius Mar 31, 2013
11a1da9
Bumping required version of ProxyManager
Ocramius Mar 31, 2013
5870fed
Docblock for ContainerBuilder#shareService
Ocramius Mar 31, 2013
695e3c5
Adding `ContainerBuilder#addClassResource`
Ocramius Mar 31, 2013
c5a5af0
Adding test to check that class resources are registered for lazy ser…
Ocramius Apr 1, 2013
29899ec
Fixing tests, registering class resources for lazy services
Ocramius Apr 1, 2013
b5d0298
Reverting import of global namespace classes
Ocramius Apr 2, 2013
cda390b
Lazier checks on the proxy structure (avoiding whitespace-based test …
Ocramius Apr 25, 2013
1eb4cf7
Getters for proxied services are public for 5.3.3 compatibility
Ocramius Apr 25, 2013
b417969
Enforcing soft dependency to ProxyManager
Ocramius Apr 25, 2013
1e24767
Reverting documentation changes, adding exception types description i…
Ocramius Apr 25, 2013
450635a
Lazier checks on the proxy structure
Ocramius Apr 27, 2013
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
Prev Previous commit
Next Next commit
Adding basic logic to generate proxy instantiation into a php dumped …
…container
  • Loading branch information
Ocramius committed Apr 30, 2013
commit 67aef456ba5c7d4a2e8ba6b1170d9f6e1cfde25e
Original file line number Diff line number Diff line change
Expand Up @@ -888,6 +888,8 @@ function (& $wrappedInstance, LazyLoadingInterface $proxy) use ($container, $def
$proxy->setProxyInitializer(null);

$wrappedInstance = $container->createService($definition, $id, false);

return true;
}
);
}
Expand Down
62 changes: 59 additions & 3 deletions src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,51 @@ private function addServiceLocalTempVariables($cId, $definition)
return $code;
}

/**
* Generates the logic required for proxy lazy loading
*
* @param string $id The service id
* @param Definition $definition
*
* @return string
*/
private function addProxyLoading($id, Definition $definition)
{
if (!($definition->isLazy() && $definition->getClass())) {
return '';
}

$class = $this->dumpValue($definition->getClass());

if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
return '';
}

// @todo this should happen directly through the factory class, but we have to ensure that the proxy
// @todo class is generated during the dump process
Copy link
Member

Choose a reason for hiding this comment

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

you should not put @todo on the second line. It makes it quite hard to read (I first thought it was a second TODO)

$methodName = 'get' . Container::camelize($id) . 'Service';

return <<<EOF
if (\$lazyLoad) {
\$factory = new \ProxyManager\Factory\LazyLoadingValueHolderFactory(new \ProxyManager\Configuration());
\$container = \$this;

return \$factory->createProxy(
$class,
function (& \$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) use (\$container) {
\$proxy->setProxyInitializer(null);

\$wrappedInstance = \$container->$methodName(false);

return true;
}
);
}


EOF;
}

/**
* Generates the require_once statement for service includes.
*
Expand Down Expand Up @@ -483,18 +528,29 @@ private function addService($id, $definition)
EOF;
}

$code = <<<EOF
if ($definition->isLazy()) {
$lazyInitialization = '$lazyLoad = true';
$lazyInitializationDoc = "\n * @param boolean \$lazyLoad whether to try lazy-loading the"
. " service with a proxy\n *";
} else {
$lazyInitialization = '';
$lazyInitializationDoc = '';
}

$code = <<<EOF

/**
* Gets the '$id' service.$doc
*
*$lazyInitializationDoc
* $return
*/
protected function get{$name}Service()
protected function get{$name}Service($lazyInitialization)
{

EOF;

$code .= $this->addProxyLoading($id, $definition);

if (!in_array($scope, array(ContainerInterface::SCOPE_CONTAINER, ContainerInterface::SCOPE_PROTOTYPE))) {
$code .= <<<EOF
if (!isset(\$this->scopedServices['$scope'])) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ public function testDumpFrozenContainerWithNoParameter()
$this->assertNotRegexp("/function getDefaultParameters\(/", $dumpedString, '->dump() does not add getDefaultParameters() method definition.');
}

public function testDumpContainerWithProxyService()
{
$container = new ContainerBuilder();
$container->register('foo', 'stdClass');
$container->getDefinition('foo')->setLazy(true);

$container->compile();

$dumper = new PhpDumper($container);

$dumpedString = $dumper->dump();
$this->assertStringEqualsFile(self::$fixturesPath.'/php/lazy_service.php', $dumpedString, '->dump() does generate proxy lazy loading logic.');
}

public function testDumpOptimizationString()
{
$definition = new Definition();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;

/**
* ProjectServiceContainer
*
* This class has been auto-generated
* by the Symfony Dependency Injection Component.
*/
class ProjectServiceContainer extends Container
{
/**
* Constructor.
*/
public function __construct()
{
$this->services =
$this->scopedServices =
$this->scopeStacks = array();

$this->set('service_container', $this);

$this->scopes = array();
$this->scopeChildren = array();
}

/**
* Gets the 'foo' service.
*
* This service is shared.
* This method always returns the same instance of the service.
*
* @param boolean $lazyLoad whether to try lazy-loading the service with a proxy
*
* @return stdClass A stdClass instance.
*/
protected function getFooService($lazyLoad = true)
{
if ($lazyLoad) {
$factory = new \ProxyManager\Factory\LazyLoadingValueHolderFactory(new \ProxyManager\Configuration());
$container = $this;

return $factory->createProxy(
'stdClass',
function (& $wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) {
$proxy->setProxyInitializer(null);

$wrappedInstance = $container->getFooService(false);

return true;
}
);
}

return $this->services['foo'] = new \stdClass();
}
}
0