Php Zend 2最佳实践-控制器外侧的服务定位器
我刚接触Zend 2,有这种情况。我想知道处理这种情况的最好方法是什么 在应用程序模块中,我有这些类Php Zend 2最佳实践-控制器外侧的服务定位器,php,zend-framework,zend-framework2,Php,Zend Framework,Zend Framework2,我刚接触Zend 2,有这种情况。我想知道处理这种情况的最好方法是什么 在应用程序模块中,我有这些类 namespace Application\Foo; class Base { protected $this->services; //service locator public function myFunc() { //needs service locator here $this->services; } }
namespace Application\Foo;
class Base {
protected $this->services; //service locator
public function myFunc() {
//needs service locator here
$this->services;
}
}
如您所见,我需要基类中的服务定位器。然后我想用A,B。。。我的控制器中的扩展类 谢谢你的建议
更新 根据jmleroux的建议,我更新了代码,使其看起来像这样
namespace Application\Foo;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class Base implements ServiceLocatorAwareInterface {
protected $this->services; //service locator
public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
$this->services = $serviceLocator;
}
public function getServiceLocator() {
return $this->services;
}
public function myFunc() {
//needs service locator here
$this->services;
}
}
module.conf.php
service_manager => array(
'invokables' => array(
'my_ser' => 'Application\Foo\Base'
)
)
在我的控制器中
$this->serviceLocator->get('my_ser');
返回已加载服务定位器的基类
现在我的问题是如何在加载服务定位器的情况下获得扩展类(A,B…)。自
$x = new \Application\Foo\A();
未加载服务定位器。我是否必须将所有扩展类作为可调用项添加到模块配置中?还是有更好的选择
再次感谢
更新2 特别感谢大家(@jmleroux)的支持。找到了这些解决方案,我将它们添加到这里,认为这会帮助其他人 注意:只是一个大概的想法。名称空间和类名不准确 解决方案1(推荐)-带有ServiceLocatorAwareInterface/ServiceLocatorAwareTrit for php 5.4+ 每个类实现ServiceLocatorAwareInterface并将其添加到服务管理器
namespace Application\Foor;
class A implements ServiceLocatorAwareInterface {
protected $services;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
$this->services = $serviceLocator;
}
public function getServiceLocator() {
return $this->services;
}
}
class B implements ServiceLocatorAwareInterface {
use ServiceLocatorAwareTrait;
}
module.conf.php(或在模块getServiceConfig()函数内)
在控制器内按名称调用服务
解决方案2-使用AbstractFactoryInterface 创建一个工厂类
class MyFac implements AbstractFactoryInterface {
public function canCreateServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName) {
if (class_exists($requestedName)){ \\eg. check Application\Foo\A exists
return true;
}
return false;
}
public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName) {
$class = new $requestedName; \\eg. creates an instance of Application\Foo\A
$class->setServiceLocator($locator); \\make sure your class has this method
return new $class;
}
}
module.conf.php(或在模块getServiceConfig()函数内)
在控制器中调用
$this->getServiceLocator()->get('Application\Foo\A');
谢谢。为了访问服务定位器,需要将基类声明为可调用的服务
如果您使用的是PHP5.4+,则可以使用谢谢。我已经更新了代码。如果
Base
的目的只是提供一个服务定位器,那么不要使用它。特别是在PHP5.4下,只需实现接口并使用ServiceLocatorAwareTrit
并将类A和B声明为可调用的。如果您真的想集中实例化,还可以使用AbstractFactory
来回答您的新问题如果您想注入服务定位器,那么您必须将所有子类作为可调用的并通过服务管理器加载。如果您只是用new实例化它们,那么即使父对象是可调用的,它也不会起作用。谢谢大家,对于我目前的情况,使用ServiceLocatorAwareInterface似乎是最好的选择@jmleroux仅供将来参考,我想知道如何实现AbstractFactory,你能给我举个好例子吗?这篇文章很清楚:谢谢。这篇文章帮助了我。
'service_manager' => array(
'invokables' => array(
'my_ser_a' => 'Application\Foo\A',
'my_ser_b' => 'Application\Foo\B',
......
)
)
class MyFac implements AbstractFactoryInterface {
public function canCreateServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName) {
if (class_exists($requestedName)){ \\eg. check Application\Foo\A exists
return true;
}
return false;
}
public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName) {
$class = new $requestedName; \\eg. creates an instance of Application\Foo\A
$class->setServiceLocator($locator); \\make sure your class has this method
return new $class;
}
}
'service_manager' => array(
'abstract_factories' => array(
'Application\Foo\MyFac'
)
)
$this->getServiceLocator()->get('Application\Foo\A');