在 Controller 中我可以使用此代码调用服务
$this->getServiceLocator()->get('MyServiceName');
效果非常酷。
我在 zf2 中创建了一个自定义库。(/vender/API)
我需要访问使用静态方法加载的所有服务。(如果可能的话)
仅举个例子。
我创建了这个自定义类。(这个(自定义)类的想法是不同的,它必须是独立的)
class Test extends AbstractModel {
protected $identifier;
protected $fullName;
protected $someText;
public function getService(){
}
}
如何使用静态方法/或类中我不知道的东西调用加载的服务?
谢谢
最佳答案
别这样做!之前已经讨论过,您最终可以阅读discussion on the mailing list ,其中也有一些很好的例子。
假设您的类 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'
在您的应用程序中可用。
无论如何,您刚刚创建的内容有两个大缺陷:
使用服务定位时应注意一些陷阱。这是service location的问题由于其性质本身:
- 您正在将代码绑定(bind)到服务定位器,而检索其他服务的实例可能不是您的类的问题。如果它们定义明确并且始终相同,则注入(inject)它们
- 您在类中使用字符串作为服务名称。这使得将代码移植到服务名称可能完全不同的另一个应用程序变得非常困难
- 您的代码可能会因服务定位器故障(未找到服务)而失败。由于您仅在需要时才访问服务,因此可能会延迟此故障。在复杂的应用程序上进行调试可能并非易事
您在此尝试在模型/实体中使用服务(和服务定位器)。这种误解/误用可能来自于您习惯于 active-record pattern ,其中很多逻辑是表示 DB 记录的对象的一部分,例如 ZF1 中的
Zend_Db
。由于ZF2中的服务非常容易定义和使用,因此请将此类逻辑移至服务中。您上面描述的是一个更像值对象或实体的类,并且不应该包含复杂的业务逻辑。
我还在 why you should use use IOC instead of service location 上写了一篇博文如果您有兴趣(第二段描述了服务位置的陷阱)。
关于php - Zendframework 2 使用静态方法调用服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15156362/