Skip to content
This repository was archived by the owner on Feb 6, 2020. It is now read-only.

Commit 928ed08

Browse files
committed
Merge pull request #106 from Moln/remove-duplicate-abstract-factory
Repeated AbstractFactory may occur in ServiceManager. Conflicts: src/ServiceManager.php
2 parents bb04e03 + 2234f10 commit 928ed08

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed

src/ServiceManager.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ class ServiceManager implements ServiceLocatorInterface
133133
*/
134134
protected $configured = false;
135135

136+
/**
137+
* Cached abstract factories from string.
138+
*
139+
* @var array
140+
*/
141+
private $cachedAbstractFactories = [];
142+
136143
/**
137144
* Constructor.
138145
*
@@ -512,11 +519,17 @@ private function resolveAbstractFactories(array $abstractFactories)
512519
{
513520
foreach ($abstractFactories as $abstractFactory) {
514521
if (is_string($abstractFactory) && class_exists($abstractFactory)) {
515-
$abstractFactory = new $abstractFactory();
522+
//Cached string
523+
if (!isset($this->cachedAbstractFactories[$abstractFactory])) {
524+
$this->cachedAbstractFactories[$abstractFactory] = new $abstractFactory();
525+
}
526+
527+
$abstractFactory = $this->cachedAbstractFactories[$abstractFactory];
516528
}
517529

518530
if ($abstractFactory instanceof Factory\AbstractFactoryInterface) {
519-
$this->abstractFactories[] = $abstractFactory;
531+
$abstractFactoryObjHash = spl_object_hash($abstractFactory);
532+
$this->abstractFactories[$abstractFactoryObjHash] = $abstractFactory;
520533
continue;
521534
}
522535

test/CommonServiceLocatorBehaviorsTrait.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Zend\ServiceManager\Factory\InvokableFactory;
2222
use Zend\ServiceManager\Initializer\InitializerInterface;
2323
use Zend\ServiceManager\ServiceLocatorInterface;
24+
use ZendTest\ServiceManager\TestAsset\CallTimesAbstractFactory;
2425
use ZendTest\ServiceManager\TestAsset\FailingAbstractFactory;
2526
use ZendTest\ServiceManager\TestAsset\FailingFactory;
2627
use ZendTest\ServiceManager\TestAsset\InvokableObject;
@@ -139,6 +140,45 @@ public function testCanCreateServiceWithAbstractFactory()
139140
$serviceManager->get(DateTime::class);
140141
}
141142

143+
public function testCallTwiceWithDifferentInstanceAbstractFactories()
144+
{
145+
CallTimesAbstractFactory::setCallTimes(0);
146+
147+
$obj1 = new CallTimesAbstractFactory();
148+
$obj2 = new CallTimesAbstractFactory();
149+
150+
$serviceManager = $this->createContainer([
151+
'abstract_factories' => [
152+
$obj1,
153+
$obj2,
154+
]
155+
]);
156+
$serviceManager->addAbstractFactory($obj1);
157+
$serviceManager->addAbstractFactory($obj2);
158+
$serviceManager->has(stdClass::class);
159+
160+
$this->assertEquals(2, CallTimesAbstractFactory::getCallTimes());
161+
}
162+
163+
/**
164+
* A new test with the same instance of `CallTimesAbstractFactory` should be provided.
165+
*/
166+
public function testCallOnlyOnceWithSameInstanceAbstractFactory()
167+
{
168+
CallTimesAbstractFactory::setCallTimes(0);
169+
170+
$serviceManager = $this->createContainer([
171+
'abstract_factories' => [
172+
CallTimesAbstractFactory::class,
173+
CallTimesAbstractFactory::class,
174+
]
175+
]);
176+
$serviceManager->addAbstractFactory(CallTimesAbstractFactory::class);
177+
$serviceManager->has(stdClass::class);
178+
179+
$this->assertEquals(1, CallTimesAbstractFactory::getCallTimes());
180+
}
181+
142182
public function testCanCreateServiceWithAlias()
143183
{
144184
$serviceManager = $this->createContainer([
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Zend Framework (http://framework.zend.com/)
4+
*
5+
* @link http://github.com/zendframework/zf2 for the canonical source repository
6+
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7+
* @license http://framework.zend.com/license/new-bsd New BSD License
8+
*/
9+
10+
namespace ZendTest\ServiceManager\TestAsset;
11+
12+
use Interop\Container\ContainerInterface;
13+
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
14+
15+
class CallTimesAbstractFactory implements AbstractFactoryInterface
16+
{
17+
protected static $callTimes = 0;
18+
19+
/**
20+
* {@inheritDoc}
21+
*/
22+
public function canCreate(ContainerInterface $container, $name)
23+
{
24+
self::$callTimes++;
25+
26+
return false;
27+
}
28+
29+
/**
30+
* {@inheritDoc}
31+
*/
32+
public function __invoke(ContainerInterface $container, $className, array $options = null)
33+
{
34+
}
35+
36+
/**
37+
* @return int
38+
*/
39+
public static function getCallTimes()
40+
{
41+
return self::$callTimes;
42+
}
43+
44+
/**
45+
* @param int $callTimes
46+
*/
47+
public static function setCallTimes($callTimes)
48+
{
49+
self::$callTimes = $callTimes;
50+
}
51+
}

0 commit comments

Comments
 (0)