【问题标题】:Zendframework 2 Call services using static methodsZendframework 2 使用静态方法调用服务
【发布时间】:2013-02-15 20:57:34
【问题描述】:


在控制器中,我可以使用此代码调用服务

$this->getServiceLocator()->get('MyServiceName');

效果很不错。

我在 zf2 中创建了一个自定义库。(/vender/API) 我需要访问使用静态方法加载的所有服务。(如果可能的话) 举个例子。
我创建了这个自定义类。(这个(自定义)类的思想不同,必须是独立的)

class Test extends AbstractModel {
    protected $identifier;
    protected $fullName;
    protected $someText;

    public function getService(){

    }
}

如何使用静态方法/或我在类中不知道的方法调用加载的服务?
谢谢

【问题讨论】:

  • 你为什么要这样做?如果您想访问所有服务,只需__construct(ServiceLocatorInterface $serviceLocator) { ... }
  • Ocramius 我正在考虑创建 FactoryInterface 并实现它。

标签: php events zend-framework2


【解决方案1】:

不要那样做!之前已经讨论过了,你最终可以阅读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本身的问题:

    1. 您正在将代码绑定到服务定位器,而检索其他服务的实例可能不是您的类的问题。如果它们定义明确且始终相同,则注入它们
    2. 您在类中使用字符串作为服务名称。这使得将您的代码移植到服务名称可能完全不同的另一个应用程序变得非常困难
    3. 您的代码可能由于服务定位器故障(未找到服务)而失败。仅在需要时才访问服务这一事实可能会延迟此故障。在复杂的应用程序上进行调试可能并非易事
  • 您在此尝试在模型/实体中使用服务(和服务定位器)。这种误解/误用可能是因为您习惯了active-record pattern,其中很多逻辑是表示数据库记录的对象的一部分,就像ZF1 中的Zend_Db。由于 ZF2 中的服务很容易定义和使用,所以请在服务中移动这样的逻辑。您上面描述的是一个更像值对象或实体的类,不应包含复杂的业务逻辑。

如果您有兴趣,我还在why you should use use IOC instead of service location 上写了一篇博文(第二段描述了服务定位的陷阱)。

【讨论】:

  • 非常感谢。你帮助了我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多