PHP Conference Japan 2024

ReflectionClass::newLazyGhost

(PHP 8 >= 8.4.0)

ReflectionClass::newLazyGhostСоздаёт новый экземпляр ленивого призрака

Описание

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

Метод создаёт новый ленивый экземпляр-призрак класса и прикрепляет к экземпляру ленивого призрака инициализатор initializer. Конструктор класса не вызывается, и свойствам не устанавливаются их значения по умолчанию. Однако инициализатор initializer автоматически вызывается и инициализирует объект при первом наблюдении за объектом или первой модификации объекта. Смотрите описания, которые содержатся в секциях «Триггеры инициализации» и «Последовательность инициализации».

Список параметров

initializer
Инициализатор — callback-функция со следующей сигнатурой:

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
10 days 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;

?>
To Top