PHPackages                             neontsun/lazy-object - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. neontsun/lazy-object

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

neontsun/lazy-object
====================

Wrapper for native lazy object in php 8.4

2.1.1(1y ago)01.1k—3.6%MITPHPPHP ^8.4

Since Feb 25Pushed 1y ago1 watchersCompare

[ Source](https://github.com/neontsun/lazy-object)[ Packagist](https://packagist.org/packages/neontsun/lazy-object)[ RSS](/packages/neontsun-lazy-object/feed)WikiDiscussions main Synced yesterday

READMEChangelog (10)Dependencies (3)Versions (11)Used By (0)

neontsun/lazy-object
====================

[](#neontsunlazy-object)

[![Latest Stable Version](https://camo.githubusercontent.com/85a283d09ed8cd8a8d59960baf47e9f8e9abb4d9a02cc25bd83ea37fceed65ae/68747470733a2f2f706f7365722e707567782e6f72672f6e656f6e7473756e2f6c617a792d6f626a6563742f763f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/neontsun/lazy-object)[![PHP Version Require](https://camo.githubusercontent.com/3acfa6818acb22f6998882cfcc721e916a4f19b2902284255cb9e433ca33bbd8/68747470733a2f2f706f7365722e707567782e6f72672f6e656f6e7473756e2f6c617a792d6f626a6563742f726571756972652f7068703f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/neontsun/lazy-object)[![License](https://camo.githubusercontent.com/c9160137cd3cf2f835da2c7bf0465ef89e1bae087204cd7f01ed35b614645ff2/68747470733a2f2f706f7365722e707567782e6f72672f6e656f6e7473756e2f6c617a792d6f626a6563742f6c6963656e73653f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/neontsun/lazy-object)[![Total Downloads](https://camo.githubusercontent.com/405877e819dac22278d16a8062801a67f5baa567934040bf9e6d0516d8624828/68747470733a2f2f706f7365722e707567782e6f72672f6e656f6e7473756e2f6c617a792d6f626a6563742f646f776e6c6f6164733f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/neontsun/lazy-object)[![Latest Unstable Version](https://camo.githubusercontent.com/1af99c0a6c2570c22b9d8176cde1a2721b332cb2f9a6d5cefd1db7163a23617b/68747470733a2f2f706f7365722e707567782e6f72672f6e656f6e7473756e2f6c617a792d6f626a6563742f762f756e737461626c653f7374796c653d666f722d7468652d6261646765)](https://packagist.org/packages/neontsun/lazy-object)

Wrapper package over native [lazy object](https://www.php.net/manual/en/language.oop5.lazy-objects.php) functionality in PHP

Installation
------------

[](#installation)

You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/):

```
composer require neontsun/lazy-object

```

If you only need this library during development, for instance to run your project's test suite, then you should add it as a development-time dependency:

```
composer require --dev neontsun/lazy-object

```

Usage
-----

[](#usage)

Add attribute to constructor fields that should be lazy loaded. If a constructor field is not marked with the lazy loading attribute, it will be considered a non-lazy field, the value of which must be passed through the **property** builder method.

```
final readonly class User
{
    public function __construct(
        private(set) string $id,
        #[Lazy]
        private(set) string $name,
        #[Lazy]
        private(set) int $age,
        #[Lazy]
        private(set) string $birthday,
    ) {}
}
```

There are two ways to create a lazy object - through a factory and through the implementation of the lazy loading interface by a class. In the first option, the phpstorm and static analyzers will not know what type was returned after creation, but this is solved by narrowing the type through **instanceof**, in the second option, the type of the created object will be available.

### With factory

[](#with-factory)

```
use Neontsun\LazyObject\Attribute\Lazy;

final readonly class Test
{
    public function __construct(
        private(set) string $uuid,
        #[Lazy]
        private(set) array $data,
    ) {}
}
```

```
use Neontsun\LazyObject\LazyObjectFactory;
use Neontsun\LazyObject\DTO\Property;

$factory = new LazyObjectFactory();

$ghost = $factory
    ->ghost(Test::class)
    ->property('uuid', 'uuid')
    ->initializer(static function (): iterable {
        yield new Property(
            name: 'data',
            value: [1, 2, 3],
        );
    })
    ->build();

var_dump(new ReflectionClass(Test::class)->isUninitializedLazyObject($ghost));
var_dump($ghost);
```

The code above yields the output below:

```
bool(true)

lazy ghost object(Test)#402 (1) {
    ["uuid"]=>
    string(4) "uuid"
    ["data"]=>
    uninitialized(array)
}

```

### With interface

[](#with-interface)

```
use Neontsun\LazyObject\Attribute\Lazy;
use Neontsun\LazyObject\Contract\Builder\LazyGhostBuilderInterface;
use Neontsun\LazyObject\Contract\LazyInterface;
use Neontsun\LazyObject\Contract\LazyObjectFactoryInterface;
use Override;
use ReflectionClass;

final readonly class Test implements LazyInterface
{
    public function __construct(
        private(set) string $uuid,
        #[Lazy]
        private(set) array $data,
    ) {}

    #[Override]
    public static function lazy(LazyObjectFactoryInterface $factory): LazyGhostBuilderInterface
    {
        return $factory->ghost(self::class);
    }

    #[Override]
    public function isUninitialized(): bool
    {
        return new ReflectionClass(self::class)->isUninitializedLazyObject($this);
    }
}
```

```
use Neontsun\LazyObject\LazyObjectFactory;
use Neontsun\LazyObject\DTO\Property;

$factory = new LazyObjectFactory();

$ghost = Test::lazy($factory)
    ->property('uuid', 'uuid')
    ->initializer(static function (): iterable {
        yield new Property(
            name: 'data',
            value: [1, 2, 3],
        );
    })
    ->build();

// $ghost is Test class for phpstrom

var_dump($ghost->isUninitializes());
var_dump($ghost);
```

The code above yields the output below:

```
bool(true)

lazy ghost object(Test)#402 (1) {
    ["uuid"]=>
    string(4) "uuid"
    ["data"]=>
    uninitialized(array)
}

```

Real life case use
------------------

[](#real-life-case-use)

```
use Neontsun\LazyObject\Attribute\Lazy;
use Neontsun\LazyObject\Contract\LazyInterface;

final readonly class Task
{
    public function __construct(
        private(set) string $title,
        private(set) string $description,
    ) {}
}

final readonly class TaskCollection implements LazyInterface
{
    /**
     * @param list $items
     */
    public function __construct(
        #[Lazy]
        private(set) array $items,
    ) {}

    #[Override]
    public static function lazy(LazyObjectFactoryInterface $factory): LazyGhostBuilderInterface
    {
        return $factory->ghost(self::class);
    }

    #[Override]
    public function isUninitialized(): bool
    {
        return new ReflectionClass(self::class)->isUninitializedLazyObject($this);
    }

    // methods...
}

final readonly class UserAggregate implements LazyInterface
{
    public function __construct(
        private(set) string $id,
        #[Lazy]
        private(set) string $name,
        #[Lazy]
        private(set) int $age,
        #[Lazy]
        private(set) string $createdAt,
        private(set) TaskCollection $tasks,
    ) {}

    #[Override]
    public static function lazy(LazyObjectFactoryInterface $factory): LazyGhostBuilderInterface
    {
        return $factory->ghost(self::class);
    }

    #[Override]
    public function isUninitialized(): bool
    {
        return new ReflectionClass(self::class)->isUninitializedLazyObject($this);
    }

    // methods...
}
```

```
use Neontsun\LazyObject\LazyObjectFactory;
use Neontsun\LazyObject\DTO\Property;

$factory = new LazyObjectFactory();

$tasksCollection = TaskCollection::lazy($factory)
    ->initializer(static function (): iterable {
        yield new Property(
            name: 'items',
            value: [
                new Task(
                    title: 'Title',
                    description: 'Description',
                ),
                // ...
            ],
        );
    })
    ->build();

$userAggregate = UserAggregate::lazy($factory)
    ->property('id', 'uuid')
    ->property('tasks', $tasksCollection)
    ->initializer(static function (): iterable {
        yield from [
            new Property(
                name: 'name',
                value: 'Name',
            ),
            new Property(
                name: 'age',
                value: 25,
            ),
            new Property(
                name: 'createdAt',
                value: '2025-01-01 12:00:00',
            ),
        ];
    })
    ->build();

var_dump($userAggregate);
var_dump($userAggregate->isUninitialized());
var_dump($userAggregate->name);
var_dump($userAggregate);
var_dump($userAggregate->isUninitialized());
var_dump($userAggregate->tasks);
var_dump($userAggregate->tasks->isUninitialized());
var_dump($userAggregate->tasks->items);
var_dump($userAggregate->tasks);
var_dump($userAggregate->tasks->isUninitialized());
```

The code above yields the output below:

```
lazy ghost object(UserAggregate)#383 (2) {
  ["id"]=>
  string(4) "uuid"
  ["name"]=>
  uninitialized(string)
  ["age"]=>
  uninitialized(int)
  ["createdAt"]=>
  uninitialized(string)
  ["tasks"]=>
  lazy ghost object(TaskCollection)#392 (0) {
    ["items"]=>
    uninitialized(array)
  }
}

bool(true)

string(4) "Name"

object(UserAggregate)#383 (5) {
  ["id"]=>
  string(4) "uuid"
  ["name"]=>
  string(4) "Name"
  ["age"]=>
  int(25)
  ["createdAt"]=>
  string(19) "2025-01-01 12:00:00"
  ["tasks"]=>
  lazy ghost object(TaskCollection)#392 (0) {
    ["items"]=>
    uninitialized(array)
  }
}

bool(false)

lazy ghost object(TaskCollection)#392 (0) {
  ["items"]=>
  uninitialized(array)
}

bool(true)

array(1) {
  [0]=>
  object(Task)#423 (2) {
    ["title"]=>
    string(5) "Title"
    ["description"]=>
    string(11) "Description"
  }
}

object(TaskCollection)#392 (1) {
  ["items"]=>
  array(1) {
    [0]=>
    object(Task)#423 (2) {
      ["title"]=>
      string(5) "Title"
      ["description"]=>
      string(11) "Description"
    }
  }
}

bool(false)

```

###  Health Score

36

—

LowBetter than 79% of packages

Maintenance46

Moderate activity, may be stable

Popularity17

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~8 days

Recently: every ~17 days

Total

10

Last Release

415d ago

Major Versions

1.1.0 → 2.0.02025-02-28

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/37738773?v=4)[Anton Kruglov](/maintainers/neontsun)[@neontsun](https://github.com/neontsun)

---

Top Contributors

[![neontsun](https://avatars.githubusercontent.com/u/37738773?v=4)](https://github.com/neontsun "neontsun (36 commits)")

---

Tags

phpproxylazyGhostlazy object8.4

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/neontsun-lazy-object/health.svg)

```
[![Health](https://phpackages.com/badges/neontsun-lazy-object/health.svg)](https://phpackages.com/packages/neontsun-lazy-object)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
