Php 在模型中获取服务
我是zend 2的新手,我想实现几个模型,这些模型可以从我想要的任何地方访问,即从控制器和其他模型访问 从控制器上看,它已经起作用了。但是我不知道如何在一个没有Php 在模型中获取服务,php,zend-framework,zend-framework2,Php,Zend Framework,Zend Framework2,我是zend 2的新手,我想实现几个模型,这些模型可以从我想要的任何地方访问,即从控制器和其他模型访问 从控制器上看,它已经起作用了。但是我不知道如何在一个没有getServiceLocator()方法的模型中执行。此外,我无法从模型内部访问服务定位器来获取配置 namespace Bsz\Services; use Zend\ServiceManager\ServiceLocatorAwareInterface; class OpenUrl implements ServiceLocator
getServiceLocator()方法的模型中执行。此外,我无法从模型内部访问服务定位器来获取配置
namespace Bsz\Services;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
class OpenUrl implements ServiceLocatorAwareInterface {
protected $serviceLocator;
public function __construct() {
$sm = $this->getServiceLocator();
$config = $sm->get('config');
var_dump($sm); //null
}
public function setServiceLocator(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
module.config.php
'service_manager' => [
'invokables' => [
'bsz\openurl' => 'Bsz\Services\OpenUrl',
]
],
namespace Bsz\Services;
use Zend\ServiceManager\ServiceManager;
class Factory {
public static function getOpenUrl(ServiceManager $sm)
{
return new \Bsz\Services\OpenUrl($sm);
}
}
'service_manager' => [
'factories' => [
'bsz\openurl' => 'Bsz\Services\Factory::getOpenUrl',
]
],
这里是我的行动,它已经起作用了
public function indexAction() {
$OpenUrl = $this->getServiceLocator()->get('bsz\openurl');
//works, is an object of type bsz\openurl.
}
所以我的问题是:如何在一个模型中正确地获得一个服务管理器,这个模型本身就被用作服务?在其他车型中如何做到这一点
我已经发现了很多类似的问题,并且尝试了很多次,但是仍然没有成功。也许Zend中的版本差异我们使用Zend 2.3.7 我现在找到了第一个问题的答案:必须将ServiceManager'注入到模型中。这只能通过工厂完成:
Factory.php
'service_manager' => [
'invokables' => [
'bsz\openurl' => 'Bsz\Services\OpenUrl',
]
],
namespace Bsz\Services;
use Zend\ServiceManager\ServiceManager;
class Factory {
public static function getOpenUrl(ServiceManager $sm)
{
return new \Bsz\Services\OpenUrl($sm);
}
}
'service_manager' => [
'factories' => [
'bsz\openurl' => 'Bsz\Services\Factory::getOpenUrl',
]
],
module.config.php
'service_manager' => [
'invokables' => [
'bsz\openurl' => 'Bsz\Services\OpenUrl',
]
],
namespace Bsz\Services;
use Zend\ServiceManager\ServiceManager;
class Factory {
public static function getOpenUrl(ServiceManager $sm)
{
return new \Bsz\Services\OpenUrl($sm);
}
}
'service_manager' => [
'factories' => [
'bsz\openurl' => 'Bsz\Services\Factory::getOpenUrl',
]
],
但是如何从另一个没有getServiceLocator
方法的模型中检索此服务 OpenUrl服务取决于它的配置。因此,配置是服务的依赖项。如果没有服务的配置,创建服务是没有意义的
您已将bsz\openurl
服务注册为“可调用”类。这意味着当您请求服务时,服务管理器将实例化Bsz\Services\OpenUrl
类,而不传入任何构造函数参数。这不是您想要的,您需要在创建类后立即进行配置
向服务工厂注册服务
要实现此ZF2,它附带了自己的工厂接口,Zend\ServiceManager\FactoryInterface
,我们的新工厂应该实现此接口
namespace Bsz\Services;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class OpenUrlFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = $this->getConfig($serviceLocator);
$service = new OpenUrl($config);
return $service;
}
protected function getConfig(ServiceLocatorInterface $serviceLocator)
{
$config = $serviceLocator->get('config');
if (! isset($config['open_url'])) {
throw new \RuntimeException('The service configuration key \'open_url\' could not be found');
}
return $config['open_url'];
}
}
现在我们可以更新module.config.php
,并将服务类型更改为工厂
'service_manager' => [
'factories' => [
'bsz\openurl' => 'Bsz\Services\OpenUrlFactory',
],
],
在此之后,如果SomeService
依赖于OpenUrl
,则可以使用新的SomeServiceFactory
重复工厂流程,其中依赖项为OpenUrl
,将ServiceManager注入类被视为不良做法;它使测试变得困难,并且不必要地将实现与ZF2耦合。首先使用工厂加载配置,然后像我的示例中那样将其传递到OpenUrl
类。那么为什么我需要setServiceLocator
方法呢?你不需要!我猜你正在阅读的例子会利用。如果有一家工厂为您提供所需的全部服务,则服务定位器不需要位于服务中,因此不需要任何setServiceLocator
等。如何在另一个模型中检索该模型?这似乎真的很复杂…将model2注入model1的构造函数中