Php 在模型中获取服务

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

我是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',
    ]
],
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的构造函数中