在模型中获取服务

时间:2015-06-16 08:20:08

标签: php zend-framework zend-framework2

我对zend 2很新,并希望实现一些模型,可以从我想要的 访问,即从控制器和其他模型访问。

来自控制器已经可以使用了。但我不知道如何在没有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',
    ]
],

这是我的行动,已经有效了

public function indexAction() {

   $OpenUrl = $this->getServiceLocator()->get('bsz\openurl');
   //works, is an object of type bsz\openurl. 
}

所以我的问题是:如何在一个本身用作服务的模型中正确获取服务管理器?如何在其他型号中执行此操作?

我发现了许多像这样的问题并尝试了很多,但仍然没有得到这个工作。也许Zend的版本差异? 我们使用Zend 2.3.7

2 个答案:

答案 0 :(得分:2)

OpenUrl服务取决于的配置。因此,配置是服务的依赖。没有它的配置就没有必要创建服务。

您已将bsz\openurl服务注册为“可调用”类。这意味着当您请求服务时,服务管理器将实例化Bsz\Services\OpenUrl类,而不传入任何构造函数参数。这不是您想要的,您需要配置为课程即将创建。

向服务工厂注册服务

  

The factory [method] pattern is a creational pattern which uses factory methods to deal with the problem of creating objects

为了实现这个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

答案 1 :(得分:0)

我现在找到第一个问题的答案:erviceManager`必须注入模型。这只能在工厂完成:

Factory.php

namespace Bsz\Services;
use Zend\ServiceManager\ServiceManager;

class Factory {

    public static function getOpenUrl(ServiceManager $sm)
    {        
        return new \Bsz\Services\OpenUrl($sm);
    }
}

module.config.php

 'service_manager' => [
    'factories' => [
        'bsz\openurl' => 'Bsz\Services\Factory::getOpenUrl',            
    ]
],

但是如何从没有getServiceLocator方法的其他模型中检索此服务?