ReflectionClass::newLazyGhost

(PHP 8 >= 8.4.0)

ReflectionClass::newLazyGhost β€” Π‘ΠΎΠ·Π΄Π°Ρ‘Ρ‚ Π½ΠΎΠ²Ρ‹ΠΉ экзСмпляр Π»Π΅Π½ΠΈΠ²ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠ·Ρ€Π°ΠΊΠ°

ОписаниС

public function ReflectionClass::newLazyGhost(callable $initializer, int $options = 0): object

ΠœΠ΅Ρ‚ΠΎΠ΄ создаёт Π½ΠΎΠ²Ρ‹ΠΉ Π»Π΅Π½ΠΈΠ²Ρ‹ΠΉ экзСмпляр-ΠΏΡ€ΠΈΠ·Ρ€Π°ΠΊ класса ΠΈ прикрСпляСт ΠΊ экзСмпляру Π»Π΅Π½ΠΈΠ²ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠ·Ρ€Π°ΠΊΠ° ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ initializer. ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ‚ΠΎΡ€ класса Π½Π΅ вызываСтся, ΠΈ свойствам Π½Π΅ ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡŽΡ‚ΡΡ ΠΈΡ… значСния ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. Однако ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ initializer автоматичСски вызываСтся ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΌ наблюдСнии Π·Π° ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ ΠΈΠ»ΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Π‘ΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ описания, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ содСрТатся Π² сСкциях Β«Π’Ρ€ΠΈΠ³Π³Π΅Ρ€Ρ‹ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈΒ» ΠΈ Β«ΠŸΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈΒ».

Бписок ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ²

initializer
Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ β€” callback-функция со ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ сигнатурой:

function initializer(object $object): void
object
ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ object ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ. На этом этапС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ пСрСстаёт Π±Ρ‹Ρ‚ΡŒ Π»Π΅Π½ΠΈΠ²Ρ‹ΠΌ, Π° ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ Π½Π΅ запускаСт ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ.
Ѐункция ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° initializer Π΄ΠΎΠ»ΠΆΠ½Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ null ΠΈΠ»ΠΈ Π½Π΅ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Ρ‚ΡŒ Π½ΠΈΠΊΠ°ΠΊΠΎΠ³ΠΎ значСния.
options

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ options ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°Ρ†ΠΈΡŽ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… Ρ„Π»Π°Π³ΠΎΠ²:

ReflectionClass::SKIP_INITIALIZATION_ON_SERIALIZE
По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ сСриализация Π»Π΅Π½ΠΈΠ²ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° запускаСт Π΅Π³ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ. Установка этого Ρ„Π»Π°Π³Π° ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΈ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ ΡΠ΅Ρ€ΠΈΠ°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π»Π΅Π½ΠΈΠ²Ρ‹Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Π±Π΅Π· ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹Π΅ значСния

ΠœΠ΅Ρ‚ΠΎΠ΄ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ экзСмпляр Π»Π΅Π½ΠΈΠ²ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠ·Ρ€Π°ΠΊΠ°. ΠœΠ΅Ρ‚ΠΎΠ΄ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ стандартный, Π° Π½Π΅ Π»Π΅Π½ΠΈΠ²Ρ‹ΠΉ экзСмпляр, Ссли Ρƒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π½Π΅Ρ‚ свойств ΠΈΠ»ΠΈ всС свойства ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° статичСскиС ΠΈΠ»ΠΈ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹Π΅. Π‘ΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅ описаниС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ содСрТит сСкция Β«Π–ΠΈΠ·Π½Π΅Π½Π½Ρ‹ΠΉ Ρ†ΠΈΠΊΠ» Π»Π΅Π½ΠΈΠ²Ρ‹Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²Β».

Ошибки

ΠœΠ΅Ρ‚ΠΎΠ΄ выбросит ΠΎΡˆΠΈΠ±ΠΊΡƒ Error, Ссли класс окаТСтся Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΌ ΠΈΠ»ΠΈ Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅Ρ‚ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΉ класс, Ссли Ρ‚ΠΎΠ»ΡŒΠΊΠΎ это Π½Π΅ класс stdClass.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ #1 Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ создания Π½ΠΎΠ²ΠΎΠ³ΠΎ экзСмпляра Π»Π΅Π½ΠΈΠ²ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠ·Ρ€Π°ΠΊΠ°

<?php

class Example
{
public function
__construct(public int $prop)
{
echo
__METHOD__, "\n";
}
}

$reflector = new ReflectionClass(Example::class);
$object = $reflector->newLazyGhost(function (Example $object) {
$object->__construct(1);
});

var_dump($object);
var_dump($object instanceof Example);

// ЗапускаСт ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ свойство послС этого
var_dump($object->prop);

?>

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ выполнСния ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°:

lazy ghost object(Example)#3 (0) {
  ["prop"]=>
  uninitialized(int)
}
bool(true)
Example::__construct
int(1)

Π‘ΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅

οΌ‹Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΡ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΉ 1 note

up
1
dave1010 at gmail dot com ΒΆ
1 year ago
Simple helper function that makes it easier to understand:

<?php

function createLazyGhost(
    string $class,
    ?callable $initializer = null,
    ?array $propertySetterCallables = null
): object {
    $reflection = new ReflectionClass($class);

    return $reflection->newLazyGhost(function (object $object) use ($initializer, $propertySetterCallables) {
        // Initialize via the main initializer if provided
        if ($initializer) {
            $initializer($object);
        }

        // Set properties using the callables if provided
        if ($propertySetterCallables) {
            foreach ($propertySetterCallables as $property => $callable) {
                if (is_callable($callable)) {
                    $object->$property = $callable();
                }
            }
        }
    });
}

?>

This supports using either a main object initializer and/or property initializers.

Here's an example, where generating order IDs and calculating totals is considered expensive, so we only do it when necessary:

<?php

class Order {
    public string $orderId = '';
    public float $total = 0.0;
}

$initializer = function (Order $order) {
    $order->orderId = 'ORD12345';
};

$propertySetters = [
    'total' => fn() => 200.75,
];

// Lazy ghost with both an initializer and property callables
$lazyOrder = createLazyGhost(Order::class, $initializer, $propertySetters);

// We can now use $lazyOrder as normal, even though the properties haven't been calculated yet.

// Do something that triggers initialization
echo $lazyOrder->orderId . PHP_EOL;
echo $lazyOrder->total . PHP_EOL;

?>