ZF3: ServiceNotFoundException 在创建 class 时使用在 ServiceManager 中注册的抽象工厂
ZF3: ServiceNotFoundException while creating a class with Abstract Factory registered in ServiceManager
我对 Abstract Factories 示例有疑问。
我在使用在 ServiceManager 中注册的抽象工厂创建 class 时得到 ServiceNotFoundException
。
首先我用 composer 下载 zend-servicemanager
composer require zendframework/zend-servicemanager
然后我 运行 单个文件中的 ServiceManager 示例(为简单起见)。
<?php
require_once 'vendor/autoload.php';
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\Factory\InvokableFactory;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
Class 应该用ServiceManager获取。
class A
{
public $text;
public function __construct()
{
$this->text = "Default text";
}
}
我使用文档中的 MyAbstractFactory。
class MyAbstractFactory implements AbstractFactoryInterface
{
public function canCreate(ContainerInterface $container, $requestedName)
{
return in_array('Traversable', class_implements($requestedName), true);
}
public function __invoke(ContainerInterface $container,
$requestedName,
array $options = null)
{
return $requestedName();
}
}
我使用注册的抽象工厂创建 ServiceManager。
$serviceManager = new ServiceManager([
// Neither works
//'abstract_factories' => array('MyAbstractFactory')
'abstract_factories' => array( new MyAbstractFactory() )
//'abstract_factories' => array( MyAbstractFactory::class )
/*
'abstract_factories' => [
MyAbstractFactory::class => new MyAbstractFactory()
]
*/
]);
最后我尝试获取 class A 的实例。
$a = $serviceManager->get(A::class);
var_dump($a);
我明白了
Fatal error: Uncaught Zend\ServiceManager\Exception\ServiceNotFoundException: Unable to resolve service "A" to a factory; are you certain you provided it during configuration?
与堆栈跟踪
.\vendor\zendframework\zend-servicemanager\src\ServiceManager.php(763): Zend\ServiceManager\ServiceManager->getFactory('A') #1
.\vendor\zendframework\zend-servicemanager\src\ServiceManager.php(200): Zend\ServiceManager\ServiceManager->doCreate('A') #2
.\script.php(53): Zend\ServiceManager\ServiceManager->get('A') #3
我对问题的表述是错误的。 @rkeet 的评论说得很清楚。
因为我的 objective 是在 ServiceManager 中注册抽象工厂的工作示例,所以我 post 简化了 canCreate()
的单文件脚本只是为了检查 class 存在。
<?php
// composer require zendframework/zend-servicemanager
require_once 'vendor/autoload.php';
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
class A
{
public $text;
public function __construct()
{
$this->text = "Default text";
}
}
class MyAbstractFactory implements AbstractFactoryInterface
{
public function canCreate(ContainerInterface $container, $requestedName)
{
return class_exists($requestedName);
}
public function __invoke(ContainerInterface $container,
$requestedName,
array $options = null)
{
return new $requestedName();
}
}
$serviceManager = new ServiceManager([
//'abstract_factories' => array('MyAbstractFactory') // works
//'abstract_factories' => array( new MyAbstractFactory() ) // works
'abstract_factories' => array( MyAbstractFactory::class ) // also works
]);
try {
$a = $serviceManager->get(A::class);
var_dump($a);
echo "<br/>\n";
$b = $serviceManager->get(B::class);
var_dump($b);
} catch (Exception $e) {
echo $e->getMessage() . "<br/>\n";
echo "{$e->getFile()} ({$e->getLine()})";
}
?>
正如@rkeet 指出的那样,如果有人需要原始示例工作,class A
应该实施 Traversable.
我对 Abstract Factories 示例有疑问。
我在使用在 ServiceManager 中注册的抽象工厂创建 class 时得到 ServiceNotFoundException
。
首先我用 composer 下载 zend-servicemanager
composer require zendframework/zend-servicemanager
然后我 运行 单个文件中的 ServiceManager 示例(为简单起见)。
<?php
require_once 'vendor/autoload.php';
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\Factory\InvokableFactory;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
Class 应该用ServiceManager获取。
class A
{
public $text;
public function __construct()
{
$this->text = "Default text";
}
}
我使用文档中的 MyAbstractFactory。
class MyAbstractFactory implements AbstractFactoryInterface
{
public function canCreate(ContainerInterface $container, $requestedName)
{
return in_array('Traversable', class_implements($requestedName), true);
}
public function __invoke(ContainerInterface $container,
$requestedName,
array $options = null)
{
return $requestedName();
}
}
我使用注册的抽象工厂创建 ServiceManager。
$serviceManager = new ServiceManager([
// Neither works
//'abstract_factories' => array('MyAbstractFactory')
'abstract_factories' => array( new MyAbstractFactory() )
//'abstract_factories' => array( MyAbstractFactory::class )
/*
'abstract_factories' => [
MyAbstractFactory::class => new MyAbstractFactory()
]
*/
]);
最后我尝试获取 class A 的实例。
$a = $serviceManager->get(A::class);
var_dump($a);
我明白了
Fatal error: Uncaught Zend\ServiceManager\Exception\ServiceNotFoundException: Unable to resolve service "A" to a factory; are you certain you provided it during configuration?
与堆栈跟踪
.\vendor\zendframework\zend-servicemanager\src\ServiceManager.php(763): Zend\ServiceManager\ServiceManager->getFactory('A') #1
.\vendor\zendframework\zend-servicemanager\src\ServiceManager.php(200): Zend\ServiceManager\ServiceManager->doCreate('A') #2
.\script.php(53): Zend\ServiceManager\ServiceManager->get('A') #3
我对问题的表述是错误的。 @rkeet 的评论说得很清楚。
因为我的 objective 是在 ServiceManager 中注册抽象工厂的工作示例,所以我 post 简化了 canCreate()
的单文件脚本只是为了检查 class 存在。
<?php
// composer require zendframework/zend-servicemanager
require_once 'vendor/autoload.php';
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\Factory\AbstractFactoryInterface;
class A
{
public $text;
public function __construct()
{
$this->text = "Default text";
}
}
class MyAbstractFactory implements AbstractFactoryInterface
{
public function canCreate(ContainerInterface $container, $requestedName)
{
return class_exists($requestedName);
}
public function __invoke(ContainerInterface $container,
$requestedName,
array $options = null)
{
return new $requestedName();
}
}
$serviceManager = new ServiceManager([
//'abstract_factories' => array('MyAbstractFactory') // works
//'abstract_factories' => array( new MyAbstractFactory() ) // works
'abstract_factories' => array( MyAbstractFactory::class ) // also works
]);
try {
$a = $serviceManager->get(A::class);
var_dump($a);
echo "<br/>\n";
$b = $serviceManager->get(B::class);
var_dump($b);
} catch (Exception $e) {
echo $e->getMessage() . "<br/>\n";
echo "{$e->getFile()} ({$e->getLine()})";
}
?>
正如@rkeet 指出的那样,如果有人需要原始示例工作,class A
应该实施 Traversable.