Skip to content

Commit aa2a0b0

Browse files
committed
wip
1 parent f70df8c commit aa2a0b0

File tree

4 files changed

+86
-6
lines changed

4 files changed

+86
-6
lines changed

src/Illuminate/Container/Attributes/Bind.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,42 @@
33
namespace Illuminate\Container\Attributes;
44

55
use Attribute;
6+
use InvalidArgumentException;
67

7-
#[Attribute(Attribute::TARGET_CLASS)]
8+
#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]
89
class Bind
910
{
1011
/**
11-
* @param class-string $concrete The concrete class to bind to.
12+
* The concrete class to bind to.
13+
*
14+
* @var class-string
15+
*/
16+
public string $concrete;
17+
18+
/**
19+
* Only use the bindings in this environment.
20+
*
21+
* @var array<int, string>
22+
*/
23+
public array $environments = [];
24+
25+
/**
26+
* @param class-string $concrete
27+
* @param array<int, string>|string $environments
28+
*
29+
* @throws \InvalidArgumentException
1230
*/
1331
public function __construct(
14-
public string $concrete,
32+
string $concrete,
33+
string|array $environments = ['*'],
1534
) {
35+
$environments = is_array($environments) ? $environments : [$environments];
36+
37+
if ($environments === []) {
38+
throw new InvalidArgumentException('The environment property must be set and cannot be empty.');
39+
}
40+
41+
$this->concrete = $concrete;
42+
$this->environments = $environments;
1643
}
1744
}

src/Illuminate/Container/Container.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,13 @@ class Container implements ArrayAccess, ContainerContract
186186
*/
187187
protected $checkedForBindings = [];
188188

189+
/**
190+
* The callback used to determine the Container's environment.
191+
*
192+
* @var (callable(array<int, string>|string): bool|string)|null
193+
*/
194+
protected $environmentResolver = null;
195+
189196
/**
190197
* Define a contextual binding.
191198
*
@@ -998,7 +1005,22 @@ protected function getConcrete($abstract)
9981005
*/
9991006
protected function getConcreteBindingFromAttributes($abstract, $reflectedAttributes)
10001007
{
1001-
$this->bind($abstract, $reflectedAttributes[0]->newInstance()->concrete);
1008+
$concrete = null;
1009+
1010+
foreach($reflectedAttributes as $reflectedAttribute) {
1011+
$instance = $reflectedAttribute->newInstance();
1012+
if ($instance->environments === ['*'] || $this->getEnvironment($instance->environments)) {
1013+
$concrete = $instance->concrete;
1014+
1015+
break;
1016+
}
1017+
}
1018+
1019+
if ($concrete === null) {
1020+
return $abstract;
1021+
}
1022+
1023+
$this->bind($abstract, $concrete);
10021024

10031025
return $this->bindings[$abstract]['concrete'];
10041026
}
@@ -1605,6 +1627,27 @@ protected function getExtenders($abstract)
16051627
return $this->extenders[$this->getAlias($abstract)] ?? [];
16061628
}
16071629

1630+
/**
1631+
* @param (callable(array<int, string>): bool)|null $callback
1632+
*/
1633+
public function resolveEnvironmentUsing(?callable $callback)
1634+
{
1635+
$this->environmentResolver = $callback;
1636+
}
1637+
1638+
/**
1639+
* Get the environment for the Container.
1640+
*
1641+
* @param array<int, string>|string $environments
1642+
* @return ($environments is array ? bool : string)
1643+
*/
1644+
public function getEnvironment($environments)
1645+
{
1646+
return $this->environmentResolver === null
1647+
? false
1648+
: call_user_func($this->environmentResolver, $environments);
1649+
}
1650+
16081651
/**
16091652
* Remove all of the extender callbacks for a given type.
16101653
*
@@ -1674,6 +1717,7 @@ public function flush()
16741717
$this->abstractAliases = [];
16751718
$this->scopedInstances = [];
16761719
$this->checkedForBindings = [];
1720+
$this->environmentResolver = null;
16771721
}
16781722

16791723
/**

src/Illuminate/Foundation/Bootstrap/LoadConfiguration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public function bootstrap(Application $app)
4343
// values that were loaded. We will pass a callback which will be used to get
4444
// the environment in a web context where an "--env" switch is not present.
4545
$app->detectEnvironment(fn () => $config->get('app.env', 'production'));
46+
$app->resolveEnvironmentUsing($app->environment(...));
4647

4748
date_default_timezone_set($config->get('app.timezone', 'UTC'));
4849

tests/Container/ContainerTest.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -756,11 +756,17 @@ public function testContainerSingletonAttribute()
756756
public function testContainerScopedAttribute()
757757
{
758758
$container = new Container;
759+
$container->resolveEnvironmentUsing(fn ($arr) => $arr === 'test');
759760
$firstInstantiation = $container->get(ContainerScopedAttribute::class);
760761
$secondInstantiation = $container->get(ContainerScopedAttribute::class);
761762

762763
$this->assertSame($firstInstantiation, $secondInstantiation);
763764

765+
// With a different environment
766+
$container->resolveEnvironmentUsing(fn ($arr) => $arr === 'test2');
767+
$thirdInstantiation = $container->get(ContainerScopedAttribute::class);
768+
$this->assertSame($firstInstantiation, $thirdInstantiation);
769+
764770
$container->forgetScopedInstances();
765771

766772
$thirdInstantiation = $container->get(ContainerScopedAttribute::class);
@@ -770,6 +776,7 @@ public function testContainerScopedAttribute()
770776
public function testBindInterfaceToSingleton()
771777
{
772778
$container = new Container;
779+
$container->resolveEnvironmentUsing(fn ($arr) => true);
773780
$firstInstantiation = $container->get(ContainerBindSingletonTestInterface::class);
774781
$secondInstantiation = $container->get(ContainerBindSingletonTestInterface::class);
775782

@@ -960,12 +967,13 @@ class ContainerScopedAttribute
960967
{
961968
}
962969

963-
#[Bind(ContainerSingletonAttribute::class)]
970+
#[Bind(ContainerSingletonAttribute::class, environments: ['foo', 'bar'])]
964971
interface ContainerBindSingletonTestInterface
965972
{
966973
}
967974

968-
#[Bind(ContainerScopedAttribute::class)]
975+
#[Bind(ContainerScopedAttribute::class, environments: ['test'])]
976+
#[Bind(ContainerScopedAttribute::class, environments: ['test2'])]
969977
interface ContainerBindScopedTestInterface
970978
{
971979
}

0 commit comments

Comments
 (0)