Skip to content

Commit

Permalink
creating lazy services in PHP 8.4 WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Nov 26, 2024
1 parent 9b9bfb4 commit bc1bfbd
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
33 changes: 25 additions & 8 deletions src/DI/Definitions/ServiceDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use Nette;
use Nette\DI\ServiceCreationException;
use Nette\Utils\Strings;


/**
Expand All @@ -24,6 +25,8 @@ final class ServiceDefinition extends Definition
{
use Nette\SmartObject;

public ?bool $lazy = null;

private Statement $creator;

/** @var Statement[] */
Expand Down Expand Up @@ -181,18 +184,32 @@ private function prependSelf(Statement $setup): Statement

public function generateMethod(Nette\PhpGenerator\Method $method, Nette\DI\PhpGenerator $generator): void
{
$code = $generator->formatStatement($this->creator) . ";\n";
if (!$this->setup) {
$method->setBody('return ' . $code);
return;
$lines = [];
foreach ([$this->creator, ...$this->setup] as $stmt) {
$lines[] = $generator->formatStatement($stmt) . ";\n";
}

$code = '$service = ' . $code;
foreach ($this->setup as $setup) {
$code .= $generator->formatStatement($setup) . ";\n";
$class = $this->creator->getEntity();
$lazy = PHP_VERSION_ID >= 80400
&& $this->lazy
&& is_string($class)
&& ($ancestor = ($tmp = class_parents($class)) ? array_pop($tmp) : $class)
&& !(new \ReflectionClass($ancestor))->isInternal()
&& !preg_grep('#(?:func_get_arg|func_num_args)#i', $lines); // latteFactory workaround

if ($lazy) {
$lines[0] = (new \ReflectionClass($class))->hasMethod('__construct')
? $generator->formatPhp("\$service->__construct(...?:);\n", [$this->creator->arguments])
: '';
$code = "return new ReflectionClass($class::class)->newLazyGhost(function (\$service) {\n"
. Strings::indent(implode('', $lines))
. '});';
} elseif (count($lines) === 1) {
$code = 'return ' . $lines[0];
} else {
$code = '$service = ' . implode('', $lines) . 'return $service;';
}

$code .= 'return $service;';
$method->setBody($code);
}

Expand Down
15 changes: 15 additions & 0 deletions src/DI/Extensions/DIExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Nette\DI\Extensions;

use Nette;
use Nette\DI\Definitions\ServiceDefinition;
use Tracy;


Expand All @@ -36,6 +37,7 @@ public function __construct(bool $debugMode = false)
public array $excluded = [];
public ?string $parentClass = null;
public object $export;
public bool $lazy = false;
};
$this->config->export = new class {
public bool $parameters = true;
Expand All @@ -56,6 +58,19 @@ public function loadConfiguration(): void
}


public function beforeCompile(): void
{
if ($this->config->lazy) {
$builder = $this->getContainerBuilder();
foreach ($builder->getDefinitions() as $def) {
if ($def instanceof ServiceDefinition) {
$def->lazy ??= true;
}
}
}
}


public function afterCompile(Nette\PhpGenerator\ClassType $class): void
{
if ($this->config->parentClass) {
Expand Down
1 change: 1 addition & 0 deletions src/DI/Extensions/DefinitionSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ private static function getServiceSchema(): Schema
'tags' => Expect::array(),
'reset' => Expect::array(),
'alteration' => Expect::bool(),
'lazy' => Expect::bool(),
]);
}

Expand Down
4 changes: 4 additions & 0 deletions src/DI/Extensions/ServicesExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ private function updateServiceDefinition(Definitions\ServiceDefinition $definiti
if (isset($config->inject)) {
$definition->addTag(InjectExtension::TagInject, $config->inject);
}

if (isset($config->lazy)) {
$definition->lazy = $config->lazy;
}
}


Expand Down

0 comments on commit bc1bfbd

Please sign in to comment.