New Implement lazy loading objects in PHP 8.4
New Implement lazy loading objects in PHP 8.4
Video Lesson: Implement lazy loading objects in PHP 8.4
Lazy-loading objects dramatically improves both the loading performance and memory utilization of expensive objects.
Published 1 week ago
Share with colleagues:
Lesson Content
PHP 8.4 introduces native lazy loading for objects. This feature delays the instantiation of an object until you actually use it. This can dramatically improve both the loading performance and memory utilization of expensive objects.
Lazy loading objects really shines in dependency injection containers. Your app may define a few dozen services, but a request may only use a few of them. By lazy-loading services, you can avoid initializing dependencies you don't actually use.
Let's look at a practical example. Here's a class with an intentionally expensive constructor:
<?php
declare(strict_types=1);
readonly class Product
{
public function __construct(
private int $id,
private string $name,
private float $price,
private array $details = [],
) {
// Simulating an expensive operation
// Like fetching product details from a database
sleep(2);
}
public function getName(): string
{
return $this->name;
}
}
The 2-second delay simulates expensive operations like database queries or complex calculations. Without lazy loading, you'd pay this cost immediately when creating the object.
With PHP 8.4's lazy loading, we can defer this cost using the Reflection API:
<?php
require_once 'Product.php';
// Create a reflection of our class
$reflector = new ReflectionClass(Product::class);
// Create a lazy "ghost" object
$product = $reflector->newLazyGhost(function(Product $product) {
// This initializer runs only when first accessed
$product->__construct(123, 'Widget', 19.99);
});
// The Product exists but hasn't been initialized yet
// Now when we access a method, initialization happens automatically
echo $product->getName().PHP_EOL; // Now we wait for the delay then get the name
The magic happens in the initializer function. It only executes when you first access a property or method. If you never use the object, you never pay the initialization cost. This pattern works exceptionally well in data-heavy applications.
You can check if an object is still uninitialized by calling itβs isUninitializedLazyObject()
method:
if ($reflector->isUninitializedLazyObject($product)) {
echo "Product is not initialized yet".PHP_EOL;
} else {
echo "Product is initialized".PHP_EOL;
}
The benefits of these ghost objects are multiplied in large applications. You'll see reduced memory usage, faster startup times, and better overall performance β especially when dealing with complex objects or expensive database ops.