PHP Conference Nagoya 2025

ReflectionClass::newLazyGhost

(PHP 8 >= 8.4.0)

ReflectionClass::newLazyGhost新しいレイジーゴーストインスタンスを作成する

説明

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

クラスの新しいレイジーゴーストインスタンスを作成し、 initializer をアタッチします。コンストラクタは呼び出されず、 プロパティはデフォルト値に設定されません。オブジェクトの状態を 初めて参照または変更する時に、 initializerをにより自動的に初期化されます。 初期化トリガーおよび 初期化シーケンス を参照してください。

パラメータ

initializer
イニシャライザは以下のシグネチャを持つコールバックです:

initializer(object $object): void
object
初期化されるobject。この時点では、 オブジェクトはもはやレイジーとしてマークされておらず、 アクセスしても再び初期化がトリガーされることはありません。

initializer関数は null を返すか、 値を返さない必要があります。
options

optionsには以下のフラグを組み合わせて 指定できます:

ReflectionClass::SKIP_INITIALIZATION_ON_SERIALIZE
デフォルトでは、レイジーオブジェクトのシリアライズは 初期化がトリガーされます。このフラグを設定すると、 初期化せずにシリアライズできるようになります。

戻り値

レイジーゴーストインスタンスを返します。オブジェクトにプロパティがない場合、または そのプロパティがすべてstaticまたはvirtualの場合、通常の(レイジーではない)インスタンスが 返されます。 レイジーオブジェクトの ライフサイクルも参照してください。

エラー / 例外

クラスが内部クラスであるか、stdClassを除く内部クラスを 拡張している場合、Errorをスローします。

例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)

参考

add a note

User Contributed Notes 1 note

up
1
dave1010 at gmail dot com
8 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