Skip to content

Commit 2ab8538

Browse files
committed
proxy attribute
1 parent c04df13 commit 2ab8538

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Illuminate\Container\Attributes;
4+
5+
use Attribute;
6+
7+
#[Attribute(Attribute::TARGET_PROPERTY | Attribute::TARGET_CLASS)]
8+
class Proxy
9+
{
10+
}

src/Illuminate/Container/Container.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Closure;
77
use Exception;
88
use Illuminate\Container\Attributes\Bind;
9+
use Illuminate\Container\Attributes\Proxy;
910
use Illuminate\Container\Attributes\Scoped;
1011
use Illuminate\Container\Attributes\Singleton;
1112
use Illuminate\Contracts\Container\BindingResolutionException;
@@ -1108,12 +1109,13 @@ protected function isBuildable($concrete, $abstract)
11081109
* @template TClass of object
11091110
*
11101111
* @param \Closure(static, array): TClass|class-string<TClass> $concrete
1112+
* @param array<class-string> $withoutLazyFor
11111113
* @return TClass
11121114
*
11131115
* @throws \Illuminate\Contracts\Container\BindingResolutionException
11141116
* @throws \Illuminate\Contracts\Container\CircularDependencyException
11151117
*/
1116-
public function build($concrete)
1118+
public function build($concrete, $withoutLazyFor = [])
11171119
{
11181120
// If the concrete type is actually a Closure, we will just execute it and
11191121
// hand back the results of the functions, which allows functions to be
@@ -1163,6 +1165,10 @@ public function build($concrete)
11631165
return $instance;
11641166
}
11651167

1168+
if (! in_array($concrete, $withoutLazyFor) && ! empty($reflector->getAttributes(Proxy::class))) {
1169+
return proxy($concrete, fn () => $this->build($concrete, [$concrete]));
1170+
}
1171+
11661172
$dependencies = $constructor->getParameters();
11671173

11681174
// Once we have all the constructor's parameters we can create each of the

tests/Container/ContainerTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Attribute;
66
use Illuminate\Container\Attributes\Bind;
7+
use Illuminate\Container\Attributes\Proxy;
78
use Illuminate\Container\Attributes\Scoped;
89
use Illuminate\Container\Attributes\Singleton;
910
use Illuminate\Container\Container;
@@ -13,6 +14,7 @@
1314
use Illuminate\Contracts\Container\SelfBuilding;
1415
use PHPUnit\Framework\TestCase;
1516
use Psr\Container\ContainerExceptionInterface;
17+
use ReflectionClass;
1618
use stdClass;
1719
use TypeError;
1820

@@ -224,6 +226,16 @@ public function testNestedDependencyResolution()
224226
$this->assertInstanceOf(ContainerImplementationStub::class, $class->inner->impl);
225227
}
226228

229+
public function testLazyObjects()
230+
{
231+
$container = new Container;
232+
$container->bind(IContainerContractStub::class, ContainerImplementationStub::class);
233+
$class = $container->make(ProxyDependenciesClass::class);
234+
$this->assertTrue((new ReflectionClass($class))->isUninitializedLazyObject($class));
235+
$class->stubby;
236+
$this->assertFalse((new ReflectionClass($class))->isUninitializedLazyObject($class));
237+
}
238+
227239
public function testContainerIsPassedToResolvers()
228240
{
229241
$container = new Container;
@@ -1217,3 +1229,13 @@ public function __construct()
12171229
$this->userId = $_SERVER['__withFactory.userId'];
12181230
}
12191231
}
1232+
1233+
#[Proxy]
1234+
class ProxyDependenciesClass
1235+
{
1236+
public function __construct(
1237+
public IContainerContractStub $stubby
1238+
) {
1239+
//dd('i have been constructed!');
1240+
}
1241+
}

0 commit comments

Comments
 (0)