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 Dec 2, 2024
1 parent 7d387de commit fd1de71
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 9 deletions.
36 changes: 27 additions & 9 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,33 @@ private function prependSelf(Statement $setup): Statement

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

$code = '$service = ' . $code;
foreach ($this->setup as $setup) {
$code .= $setup->generateCode($generator) . ";\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])
: '';
return "return new ReflectionClass($class::class)->newLazyGhost(function (\$service) {\n"
. Strings::indent(implode('', $lines))
. '});';

} elseif (count($lines) === 1) {
return 'return ' . $lines[0];

} else {
return '$service = ' . implode('', $lines) . 'return $service;';
}

$code .= 'return $service;';
return $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
1 change: 1 addition & 0 deletions tests/DI/Compiler.loadConfig.include.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Assert::equal([
'tags' => [],
'reset' => [],
'alteration' => null,
'lazy' => null,
'defType' => Nette\DI\Definitions\ServiceDefinition::class,
],
],
Expand Down

0 comments on commit fd1de71

Please sign in to comment.