@@ -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,73 @@ 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+
948986 // public function testContainerCanCatchCircularDependency()
949987 // {
950988 // $this->expectException(\Illuminate\Contracts\Container\CircularDependencyException::class);
@@ -990,7 +1028,10 @@ interface IContainerContractStub
9901028
9911029class ContainerImplementationStub implements IContainerContractStub
9921030{
993- //
1031+ public function __construct ()
1032+ {
1033+ ConstructionNotices::$ constructed [self ::class] = true ;
1034+ }
9941035}
9951036
9961037class ContainerImplementationStubTwo implements IContainerContractStub
@@ -1000,11 +1041,18 @@ class ContainerImplementationStubTwo implements IContainerContractStub
10001041
10011042class ContainerDependentStub
10021043{
1044+ public $ value ;
10031045 public $ impl ;
10041046
10051047 public function __construct (IContainerContractStub $ impl )
10061048 {
10071049 $ this ->impl = $ impl ;
1050+ ConstructionNotices::$ constructed [self ::class] = true ;
1051+ }
1052+
1053+ public function setValue ($ value )
1054+ {
1055+ $ this ->value = $ value ;
10081056 }
10091057}
10101058
@@ -1250,15 +1298,23 @@ public function __construct()
12501298#[Lazy]
12511299class ProxyDependenciesClass
12521300{
1301+ public string $ value ;
1302+
12531303 public function __construct (
12541304 public IContainerContractStub $ stubby
12551305 ) {
1306+ ConstructionNotices::$ constructed [self ::class] = true ;
12561307 }
12571308
12581309 public function stubbyIsSet (): bool
12591310 {
12601311 return isset ($ this ->stubby );
12611312 }
1313+
1314+ public function setValue (string $ value ): void
1315+ {
1316+ $ this ->value = $ value ;
1317+ }
12621318}
12631319
12641320class ClassWithLazyDependencies
@@ -1267,10 +1323,50 @@ public function __construct(
12671323 #[Lazy]
12681324 public ContainerDependentStub $ stubby
12691325 ) {
1326+ ConstructionNotices::$ constructed [self ::class] = true ;
12701327 }
12711328
12721329 public function stubbyIsSet (): bool
12731330 {
12741331 return isset ($ this ->stubby );
12751332 }
1333+
1334+ public function bringDependencyToLife ($ value ): void
1335+ {
1336+ $ this ->stubby ->setValue ($ value );
1337+ }
1338+ }
1339+
1340+ #[Lazy]
1341+ class LazyClassWithLazyDependency
1342+ {
1343+ public string $ value ;
1344+
1345+ public function __construct (
1346+ public ProxyDependenciesClass $ wholeClassIsLazyDependency ,
1347+ public ClassWithLazyDependencies $ lazyAttributeDependency
1348+ ) {
1349+ ConstructionNotices::$ constructed [self ::class] = true ;
1350+ }
1351+
1352+ public function setValue (string $ value ): void
1353+ {
1354+ $ this ->value = $ value ;
1355+ }
1356+
1357+ public function bringDependencyToLife (string $ value ): void
1358+ {
1359+ $ this ->wholeClassIsLazyDependency ->setValue ($ value );
1360+ }
1361+ }
1362+
1363+ class ConstructionNotices
1364+ {
1365+ /** @var array<class-string, true> */
1366+ public static array $ constructed = [];
1367+
1368+ public static function reset (): void
1369+ {
1370+ self ::$ constructed = [];
1371+ }
12761372}
0 commit comments