Skip to content

lazyGhost not initializing? #17593

@tlamy

Description

@tlamy

Description

I may have found a problem with lazy ghosts, or have a fundamental misunderstanding of how it should work.

The following code is a heavily stripped down version of our application and framework code:

<?php
declare(strict_types=1);

class Dependency
{
    /** @var string */
    public const ENV_NODE = '{{@env:';
    /** @var string */
    public const ENV_NODE2 = '${';
    protected static string $node1Regex;
    protected static string $node2Regex;
    /** @var callable $envGetterFunction */
    protected $envGetterFunction;

    public function __construct()
    {
        error_log(__METHOD__ . ' called');
        self::$node1Regex = '/' . preg_quote(static::ENV_NODE, '/') . '(\w+)\}\}/';
        self::$node2Regex = '/' . preg_quote(static::ENV_NODE2, '/') . '(\w+)\}/';

        $this->envGetterFunction = static function (string $name): ?string {
            $value = getenv($name);
            return $value === false ? null : $value;
        };
    }

    public function method(string $input): bool
    {
        return preg_match(static::$node1Regex, $input) > 0;
    }

}

class Application
{
    private readonly Dependency $dependency;

    public function __construct(bool $useLazyGhosts = false)
    {
        if ($useLazyGhosts) {
            $dependencyReflect = new ReflectionClass(Dependency::class);
            $this->dependency = $dependencyReflect->newLazyGhost(function (object $instance) {
                error_log('Initializing ghost ');
                print_r($instance);
                $instance->__construct();
            });
        } else {
            $this->dependency = new Dependency();
        }
    }

    public function run(string $arg): int
    {
        $this->dependency->method($arg);

        return 0;
    }
}

$app = new Application((bool)($argv[1] ?? false));
$app->run('The quick brown fox jumps over the lazy dog.');

Resulted in this output:

PHP Fatal error:  Uncaught Error: Typed static property Dependency::$node1Regex must not be accessed before initialization in …/scratch_21.php:29
Stack trace:
#0 …/scratch_21.php(51): Dependency->method('The quick brown...')
#1 …/scratch_21.php(58): Application->run('The quick brown...')
#2 {main}

But I expected this output instead:

Initializing ghost
Dependency::__construct called

Usage: php script.php [0|1]
1 => use lazy ghosts
0 => standard construction

PHP 8.4.2 (cli) (built: Dec 17 2024 15:31:31) (NTS)

PHP Version

PHP 8.4.2

Operating System

macOS 15.2, "official" docker image

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions