Skip to content

Commit 41417ca

Browse files
committed
Merge branch 'pr2461' into 8.x
2 parents a18266c + 2971b64 commit 41417ca

File tree

4 files changed

+110
-2
lines changed

4 files changed

+110
-2
lines changed

src/Illuminate/Container/Container.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ class Container implements ArrayAccess, ContainerContract
5151
*/
5252
protected $instances = [];
5353

54+
/**
55+
* The container's scoped instances.
56+
*
57+
* @var array
58+
*/
59+
protected $scopedInstances = [];
60+
5461
/**
5562
* The registered type aliases.
5663
*
@@ -393,6 +400,36 @@ public function singletonIf($abstract, $concrete = null)
393400
}
394401
}
395402

403+
/**
404+
* Register a scoped binding in the container.
405+
*
406+
* @param string $abstract
407+
* @param \Closure|string|null $concrete
408+
* @return void
409+
*/
410+
public function scoped($abstract, $concrete = null)
411+
{
412+
$this->scopedInstances[] = $abstract;
413+
414+
$this->singleton($abstract, $concrete);
415+
}
416+
417+
/**
418+
* Register a scoped binding if it hasn't already been registered.
419+
*
420+
* @param string $abstract
421+
* @param \Closure|string|null $concrete
422+
* @return void
423+
*/
424+
public function scopedIf($abstract, $concrete = null)
425+
{
426+
if (! $this->bound($abstract)) {
427+
$this->scopedInstances[] = $abstract;
428+
429+
$this->singleton($abstract, $concrete);
430+
}
431+
}
432+
396433
/**
397434
* "Extend" an abstract type in the container.
398435
*
@@ -1307,6 +1344,18 @@ public function forgetInstances()
13071344
$this->instances = [];
13081345
}
13091346

1347+
/**
1348+
* Clear all of the scoped instances from the container.
1349+
*
1350+
* @return void
1351+
*/
1352+
public function forgetScopedInstances()
1353+
{
1354+
foreach ($this->scopedInstances as $scoped) {
1355+
unset($this->instances[$scoped]);
1356+
}
1357+
}
1358+
13101359
/**
13111360
* Flush the container of all bindings and resolved instances.
13121361
*
@@ -1319,6 +1368,7 @@ public function flush()
13191368
$this->bindings = [];
13201369
$this->instances = [];
13211370
$this->abstractAliases = [];
1371+
$this->scopedInstances = [];
13221372
}
13231373

13241374
/**

src/Illuminate/Queue/QueueServiceProvider.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,16 @@ protected function registerWorker()
166166
return $this->app->isDownForMaintenance();
167167
};
168168

169+
$resetScope = function () use ($app) {
170+
return $app->forgetScopedInstances();
171+
};
172+
169173
return new Worker(
170174
$app['queue'],
171175
$app['events'],
172176
$app[ExceptionHandler::class],
173-
$isDownForMaintenance
177+
$isDownForMaintenance,
178+
$resetScope
174179
);
175180
});
176181
}

src/Illuminate/Queue/Worker.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ class Worker
6565
*/
6666
protected $isDownForMaintenance;
6767

68+
/**
69+
* The callback used to reset the application's scope.
70+
*
71+
* @var callable
72+
*/
73+
protected $resetScope;
74+
6875
/**
6976
* Indicates if the worker should exit.
7077
*
@@ -93,17 +100,20 @@ class Worker
93100
* @param \Illuminate\Contracts\Events\Dispatcher $events
94101
* @param \Illuminate\Contracts\Debug\ExceptionHandler $exceptions
95102
* @param callable $isDownForMaintenance
103+
* @param callable|null $resetScope
96104
* @return void
97105
*/
98106
public function __construct(QueueManager $manager,
99107
Dispatcher $events,
100108
ExceptionHandler $exceptions,
101-
callable $isDownForMaintenance)
109+
callable $isDownForMaintenance,
110+
callable $resetScope = null)
102111
{
103112
$this->events = $events;
104113
$this->manager = $manager;
105114
$this->exceptions = $exceptions;
106115
$this->isDownForMaintenance = $isDownForMaintenance;
116+
$this->resetScope = $resetScope;
107117
}
108118

109119
/**
@@ -138,6 +148,10 @@ public function daemon($connectionName, $queue, WorkerOptions $options)
138148
continue;
139149
}
140150

151+
if (isset($this->resetScope)) {
152+
($this->resetScope)();
153+
}
154+
141155
// First, we will attempt to get the next job off of the queue. We will also
142156
// register the timeout handler and reset the alarm for this job so it is
143157
// not stuck in a frozen state forever. Then, we can fire off this job.

tests/Container/ContainerTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,31 @@ public function testSharedClosureResolution()
106106
$this->assertSame($firstInstantiation, $secondInstantiation);
107107
}
108108

109+
public function testScopedClosureResolution()
110+
{
111+
$container = new Container;
112+
$container->scoped('class', function () {
113+
return new stdClass;
114+
});
115+
$firstInstantiation = $container->make('class');
116+
$secondInstantiation = $container->make('class');
117+
$this->assertSame($firstInstantiation, $secondInstantiation);
118+
}
119+
120+
public function testScopedClosureResets()
121+
{
122+
$container = new Container;
123+
$container->scoped('class', function () {
124+
return new stdClass;
125+
});
126+
$firstInstantiation = $container->make('class');
127+
128+
$container->forgetScopedInstances();
129+
130+
$secondInstantiation = $container->make('class');
131+
$this->assertNotSame($firstInstantiation, $secondInstantiation);
132+
}
133+
109134
public function testAutoConcreteResolution()
110135
{
111136
$container = new Container;
@@ -122,6 +147,20 @@ public function testSharedConcreteResolution()
122147
$this->assertSame($var1, $var2);
123148
}
124149

150+
public function testScopedConcreteResolutionResets()
151+
{
152+
$container = new Container;
153+
$container->scoped(ContainerConcreteStub::class);
154+
155+
$var1 = $container->make(ContainerConcreteStub::class);
156+
157+
$container->forgetScopedInstances();
158+
159+
$var2 = $container->make(ContainerConcreteStub::class);
160+
161+
$this->assertNotSame($var1, $var2);
162+
}
163+
125164
public function testBindFailsLoudlyWithInvalidArgument()
126165
{
127166
$this->expectException(TypeError::class);

0 commit comments

Comments
 (0)