在控制器中,我可以使用此代码呼叫服务
$this->getServiceLocator()->get('MyServiceName');
它很酷。
我在zf2中创建了一个自定义库。(/vender/neneneba API(我需要访问使用静态方法加载的所有服务。(如果可能的话(只是举个例子。
我创建了这个自定义类。(这个(自定义(类的想法不同,它必须是独立的(
class Test extends AbstractModel {
protected $identifier;
protected $fullName;
protected $someText;
public function getService(){
}
}
如何使用静态方法/或类中不知道的东西来调用加载的服务
感谢
不要那样做!之前已经讨论过了,你最终可以阅读邮件列表上的讨论,其中也有一些很好的例子。
假设您的类Test
出于某种原因需要访问服务定位器,正确的方法是使用服务定位器将其实例化为硬依赖:
use Zend'ServiceManager'ServiceLocatorInterface;
class Test extends AbstractModel
{
// ...
public function __construct(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function doFoo()
{
return $this->serviceLocator->get('FooService')->foo();
}
// ...
}
通过这种方式,您可以用$test = new Test($serviceLocator);
实例化它,也可以在工厂中定义它,并让服务定位器本身为您提供一个实例:
namespace MyApp;
use Zend'ModuleManager'Feature'ServiceProviderInterface;
class Module implements ServiceProviderInterface
{
public function getServiceConfig()
{
return array(
'factories' => array(
'Test' => function ($serviceLocator) {
return new 'Test($serviceLocator);
},
),
);
}
}
这基本上使服务'Test'
可以在整个应用程序中使用。
不管怎样,你刚刚创建的东西有两个大缺陷:
在使用服务定位时,您应该注意一些陷阱。由于其性质,这是一个服务位置本身的问题:
- 您正在将代码绑定到服务定位器,而检索其他服务的实例可能不是类的问题。如果它们定义良好且始终相同,则注入它们
- 您在类中使用字符串作为服务名称。这使得很难将代码移植到另一个服务名称可能完全不同的应用程序
- 您的代码可能会由于服务定位器故障(找不到服务(而失败。此故障可能会由于您仅在需要时访问服务而延迟。在复杂的应用程序上进行调试可能并非易事
您在此尝试在模型/实体中使用服务(和服务定位器(。这种误解/误用可能源于您已经习惯了活动记录模式,其中许多逻辑是表示DB记录的对象的一部分,如ZF1中的
Zend_Db
。由于ZF2中的服务很容易定义和使用,请在服务中移动这样的逻辑。上面描述的类更像是一个值对象或实体,不应该包含复杂的业务逻辑。
我还写了一篇博客文章,讨论如果你感兴趣,为什么应该使用IOC而不是服务位置(第二段描述了服务位置的陷阱(。