@@ -226,35 +226,6 @@ public function testNestedDependencyResolution()
226226 $ this ->assertInstanceOf (ContainerImplementationStub::class, $ class ->inner ->impl );
227227 }
228228
229- public function testLazyObjects ()
230- {
231- if (version_compare (phpversion (), '8.4.0 ' , '< ' )) {
232- $ this ->markTestSkipped ();
233- }
234-
235- $ container = new Container ;
236- $ container ->bind (IContainerContractStub::class, ContainerImplementationStub::class);
237- $ class = $ container ->make (ProxyDependenciesClass::class);
238- $ this ->assertTrue ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
239- $ this ->assertTrue ($ class ->stubbyIsSet ());
240- $ this ->assertFalse ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
241- }
242-
243- public function testObjectWithLazyDependencies ()
244- {
245- if (version_compare (phpversion (), '8.4.0 ' , '< ' )) {
246- $ this ->markTestSkipped ();
247- }
248-
249- $ container = new Container ;
250- $ container ->bind (IContainerContractStub::class, ContainerImplementationStub::class);
251- $ class = $ container ->make (ClassWithLazyDependencies::class);
252- $ this ->assertFalse ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
253- $ this ->assertTrue ((new ReflectionClass (ContainerDependentStub::class))->isUninitializedLazyObject ($ class ->stubby ));
254- $ this ->assertTrue ($ class ->stubbyIsSet ());
255- $ this ->assertFalse ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
256- }
257-
258229 public function testContainerIsPassedToResolvers ()
259230 {
260231 $ container = new Container ;
@@ -945,6 +916,74 @@ public function testWithFactoryHasDependency()
945916 $ this ->assertEquals ('taylor@laravel.com ' , $ r ->email );
946917 }
947918
919+ public function testLazyObjects ()
920+ {
921+ if (version_compare (phpversion (), '8.4.0 ' , '< ' )) {
922+ $ this ->markTestSkipped ('Lazy objects are only available in 8.4 and later ' );
923+ }
924+
925+ $ container = new Container ;
926+ $ container ->bind (IContainerContractStub::class, ContainerImplementationStub::class);
927+ $ class = $ container ->make (ProxyDependenciesClass::class);
928+ $ this ->assertTrue ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
929+ $ this ->assertTrue ($ class ->stubbyIsSet ());
930+ $ this ->assertFalse ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
931+ }
932+
933+ public function testObjectWithLazyDependencies ()
934+ {
935+ if (version_compare (phpversion (), '8.4.0 ' , '< ' )) {
936+ $ this ->markTestSkipped ('Lazy objects are only available in 8.4 and later ' );
937+ }
938+
939+ $ container = new Container ;
940+ $ container ->bind (IContainerContractStub::class, ContainerImplementationStub::class);
941+ $ class = $ container ->make (ClassWithLazyDependencies::class);
942+ $ this ->assertFalse ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
943+ $ this ->assertTrue ((new ReflectionClass (ContainerDependentStub::class))->isUninitializedLazyObject ($ class ->stubby ));
944+ $ this ->assertTrue ($ class ->stubbyIsSet ());
945+ $ this ->assertFalse ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
946+ }
947+
948+ public function testLazyObjectWithLazyDependency ()
949+ {
950+ if (version_compare (phpversion (), '8.4.0 ' , '< ' )) {
951+ $ this ->markTestSkipped ('Lazy objects are only available in 8.4 and later ' );
952+ }
953+
954+ ConstructionNotices::reset ();
955+
956+ $ container = new Container ;
957+ $ container ->bind (IContainerContractStub::class, ContainerImplementationStub::class);
958+
959+ $ class = $ container ->make (LazyClassWithLazyDependency::class);
960+ // The object and its dependency are both lazy
961+ $ this ->assertCount (0 , ConstructionNotices::$ constructed );
962+ $ this ->assertTrue ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
963+
964+ // Now we call a function on the object to bring its direct dependencies to life
965+ $ class ->setValue ('hello ' );
966+
967+ // And the object overall is not lazy
968+ $ this ->assertCount (2 , ConstructionNotices::$ constructed );
969+ $ this ->assertTrue (ConstructionNotices::$ constructed [LazyClassWithLazyDependency::class]);
970+ $ this ->assertFalse ((new ReflectionClass ($ class ))->isUninitializedLazyObject ($ class ));
971+ // Nor is its non-lazy dependency
972+ $ this ->assertTrue (ConstructionNotices::$ constructed [ClassWithLazyDependencies::class]);
973+
974+ // now we bring to life `$wholeClassIsLazyDependency`
975+ $ class ->bringDependencyToLife ('child dependency ' );
976+ $ this ->assertCount (4 , ConstructionNotices::$ constructed );
977+ $ this ->assertTrue (ConstructionNotices::$ constructed [ProxyDependenciesClass::class]);
978+ // which also constructs its Container IContainerImplementationStub dependency
979+ $ this ->assertTrue (ConstructionNotices::$ constructed [ContainerImplementationStub::class]);
980+
981+ $ class ->lazyAttributeDependency ->bringDependencyToLife ('grandchild dependency ' );
982+ $ this ->assertCount (5 , ConstructionNotices::$ constructed );
983+ $ this ->assertTrue (ConstructionNotices::$ constructed [ContainerDependentStub::class]);
984+
985+ }
986+
948987 // public function testContainerCanCatchCircularDependency()
949988 // {
950989 // $this->expectException(\Illuminate\Contracts\Container\CircularDependencyException::class);
@@ -990,7 +1029,10 @@ interface IContainerContractStub
9901029
9911030class ContainerImplementationStub implements IContainerContractStub
9921031{
993- //
1032+ public function __construct ()
1033+ {
1034+ ConstructionNotices::$ constructed [self ::class] = true ;
1035+ }
9941036}
9951037
9961038class ContainerImplementationStubTwo implements IContainerContractStub
@@ -1000,11 +1042,18 @@ class ContainerImplementationStubTwo implements IContainerContractStub
10001042
10011043class ContainerDependentStub
10021044{
1045+ public $ value ;
10031046 public $ impl ;
10041047
10051048 public function __construct (IContainerContractStub $ impl )
10061049 {
10071050 $ this ->impl = $ impl ;
1051+ ConstructionNotices::$ constructed [self ::class] = true ;
1052+ }
1053+
1054+ public function setValue ($ value )
1055+ {
1056+ $ this ->value = $ value ;
10081057 }
10091058}
10101059
@@ -1250,15 +1299,23 @@ public function __construct()
12501299#[Lazy]
12511300class ProxyDependenciesClass
12521301{
1302+ public string $ value ;
1303+
12531304 public function __construct (
12541305 public IContainerContractStub $ stubby
12551306 ) {
1307+ ConstructionNotices::$ constructed [self ::class] = true ;
12561308 }
12571309
12581310 public function stubbyIsSet (): bool
12591311 {
12601312 return isset ($ this ->stubby );
12611313 }
1314+
1315+ public function setValue (string $ value ): void
1316+ {
1317+ $ this ->value = $ value ;
1318+ }
12621319}
12631320
12641321class ClassWithLazyDependencies
@@ -1267,10 +1324,50 @@ public function __construct(
12671324 #[Lazy]
12681325 public ContainerDependentStub $ stubby
12691326 ) {
1327+ ConstructionNotices::$ constructed [self ::class] = true ;
12701328 }
12711329
12721330 public function stubbyIsSet (): bool
12731331 {
12741332 return isset ($ this ->stubby );
12751333 }
1334+
1335+ public function bringDependencyToLife ($ value ): void
1336+ {
1337+ $ this ->stubby ->setValue ($ value );
1338+ }
1339+ }
1340+
1341+ #[Lazy]
1342+ class LazyClassWithLazyDependency
1343+ {
1344+ public string $ value ;
1345+
1346+ public function __construct (
1347+ public ProxyDependenciesClass $ wholeClassIsLazyDependency ,
1348+ public ClassWithLazyDependencies $ lazyAttributeDependency
1349+ ) {
1350+ ConstructionNotices::$ constructed [self ::class] = true ;
1351+ }
1352+
1353+ public function setValue (string $ value ): void
1354+ {
1355+ $ this ->value = $ value ;
1356+ }
1357+
1358+ public function bringDependencyToLife (string $ value ): void
1359+ {
1360+ $ this ->wholeClassIsLazyDependency ->setValue ($ value );
1361+ }
1362+ }
1363+
1364+ class ConstructionNotices
1365+ {
1366+ /** @var array<class-string, true> */
1367+ public static array $ constructed = [];
1368+
1369+ public static function reset (): void
1370+ {
1371+ self ::$ constructed = [];
1372+ }
12761373}
0 commit comments