Skip to content

Commit bb0cd96

Browse files
authored
Merge pull request #7868 from kenjis/fix-factories-return-new-instance
fix: Factories may not return shared instance
2 parents 1804bab + 1b88479 commit bb0cd96

File tree

2 files changed

+50
-9
lines changed

2 files changed

+50
-9
lines changed

system/Config/Factories.php

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public static function define(string $component, string $alias, string $classnam
118118
self::getOptions($component);
119119

120120
self::$aliases[$component][$alias] = $classname;
121+
self::$updated[$component] = true;
121122
}
122123

123124
/**
@@ -142,6 +143,7 @@ public static function __callStatic(string $component, array $arguments)
142143
return new $class(...$arguments);
143144
}
144145

146+
// Try to locate the class
145147
if ($class = self::locateClass($options, $alias)) {
146148
return new $class(...$arguments);
147149
}
@@ -160,14 +162,8 @@ public static function __callStatic(string $component, array $arguments)
160162
return null;
161163
}
162164

163-
self::$instances[$options['component']][$class] = new $class(...$arguments);
164-
self::$aliases[$options['component']][$alias] = $class;
165-
self::$updated[$options['component']] = true;
166-
167-
// If a short classname is specified, also register FQCN to share the instance.
168-
if (! isset(self::$aliases[$options['component']][$class])) {
169-
self::$aliases[$options['component']][$class] = $class;
170-
}
165+
self::createInstance($options['component'], $class, $arguments);
166+
self::setAlias($options['component'], $alias, $class);
171167

172168
return self::$instances[$options['component']][$class];
173169
}
@@ -179,6 +175,7 @@ public static function __callStatic(string $component, array $arguments)
179175
*/
180176
private static function getDefinedInstance(array $options, string $alias, array $arguments)
181177
{
178+
// The alias is already defined.
182179
if (isset(self::$aliases[$options['component']][$alias])) {
183180
$class = self::$aliases[$options['component']][$alias];
184181

@@ -189,15 +186,50 @@ private static function getDefinedInstance(array $options, string $alias, array
189186
return self::$instances[$options['component']][$class];
190187
}
191188

192-
self::$instances[$options['component']][$class] = new $class(...$arguments);
189+
self::createInstance($options['component'], $class, $arguments);
193190

194191
return self::$instances[$options['component']][$class];
195192
}
196193
}
197194

195+
// Try to locate the class
196+
if (! $class = self::locateClass($options, $alias)) {
197+
return null;
198+
}
199+
200+
// Check for an existing instance for the class
201+
if (isset(self::$instances[$options['component']][$class])) {
202+
self::setAlias($options['component'], $alias, $class);
203+
204+
return self::$instances[$options['component']][$class];
205+
}
206+
198207
return null;
199208
}
200209

210+
/**
211+
* Creates the shared instance.
212+
*/
213+
private static function createInstance(string $component, string $class, array $arguments): void
214+
{
215+
self::$instances[$component][$class] = new $class(...$arguments);
216+
self::$updated[$component] = true;
217+
}
218+
219+
/**
220+
* Sets alias
221+
*/
222+
private static function setAlias(string $component, string $alias, string $class): void
223+
{
224+
self::$aliases[$component][$alias] = $class;
225+
self::$updated[$component] = true;
226+
227+
// If a short classname is specified, also register FQCN to share the instance.
228+
if (! isset(self::$aliases[$component][$class]) && ! self::isNamespaced($alias)) {
229+
self::$aliases[$component][$class] = $class;
230+
}
231+
}
232+
201233
/**
202234
* Is the component Config?
203235
*

tests/system/Config/FactoriesTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace CodeIgniter\Config;
1313

1414
use CodeIgniter\Test\CIUnitTestCase;
15+
use Config\App;
1516
use Config\Database;
1617
use InvalidArgumentException;
1718
use ReflectionClass;
@@ -322,6 +323,14 @@ public function testCanLoadTwoCellsWithSameShortName()
322323
$this->assertNotSame($cell1, $cell2);
323324
}
324325

326+
public function testCanLoadSharedConfigWithDifferentAlias()
327+
{
328+
$config1 = Factories::config(App::class);
329+
$config2 = Factories::config('App');
330+
331+
$this->assertSame($config1, $config2);
332+
}
333+
325334
public function testDefineSameAliasTwiceWithDifferentClasses()
326335
{
327336
$this->expectException(InvalidArgumentException::class);

0 commit comments

Comments
 (0)