ZendFramework 2.0.0beta4 Service Manager配置 - 子键之间的差异

时间:2012-06-23 03:25:31

标签: php zend-framework2 zend-db servicemanager

编辑:在发布此问题几周后,Evan Coury撰写了一篇关于ZF2 ServiceManager主题的精彩博文,我在这里找到了我的问题的最佳答案:{{3 }}

-

我正在使用ZendFramework 2.0.0beta4开发一个项目,并且无法使用Zend \ ServiceManager来处理依赖项。这是当前的http://blog.evan.pro/introduction-to-the-zend-framework-2-servicemanager

它列出了在使用ServiceManager注册类时要使用的6个子键,以便在我们的模块中使用: abstract_factories 别名工厂 invokables 服务共享。如果我只想注册一个模型类,我将在我的控制器中使用它从数据库中提取数据,哪一个最好?我特意尝试将下面显示的ZF2 ServiceManager documentation示例改编为我自己的应用程序(DashboardTable是模型),此示例使用工厂方式。

public function getServiceConfiguration()
{
    return array(
        'factories' => array(
            'album-table' => function($sm) {
                $dbAdapter = $sm->get('db-adapter');
                $table = new DashboardTable($dbAdapter);
                return $table;
            },
            'test-model' => Dashboard\Model\TestModel(),
        ),
    );
}

但是,我不知道'db-adapter'是如何进入我在SkeletonApplication的单独工作示例中的ServiceManager($ sm)的 - 它与自动加载的global.php配置文件中的条目有关。有一个包含DB信息的'db'条目。因为我不确切知道如何从配置文件到ServiceManager,我在下面创建了一个简单的条目,以减少问题到它的基本组件 - “测试模型”。当我注释掉“dashboard-table”条目并从我的控制器中的TestModel调用一个函数时,它只输出一些文本。下面是我的Module.php

中的ServiceManager配置
<?php

namespace Dashboard\Model;

class TestModel {

public function testMethod()
{
    $testResult = "Hello";
    return $testResult;
}

}

然后从我的控制器传递到视图:

<?php

namespace Dashboard\Controller;

use Zend\Mvc\Controller\ActionController;
use Zend\View\Model\ViewModel;
use Dashboard\Model\AlbumTable;
use Dashboard\Model\TestModel;
use Dashboard\Model\Dashboard;

class DashboardController extends ActionController
{
    public function indexAction()
    {   
        return new ViewModel(array(
            'users' => $this->getTestModel()->testMethod(),
        ));
    }

    public function getAlbumTable()
    {
        if (!$this->albumTable) {
            $sm = $this->getServiceLocator();
            $this->albumTable = $sm->get('album-table');
        }
        return $this->albumTable;
    }

    public function getTestModel()
    {
        if (!$this->testModel) {
            $sm = $this->getServiceLocator();
            $this->testModel = $sm->get('test-model');
        }
        return $this->testModel;
    }

}

这段代码给了我一个完全空白的页面,没有错误。当我从Module.php中注释掉ServiceManager配置并只渲染一个新的ViewModel而没有在我的DashboardController.php文件中传递任何参数时,页面正常渲染 - 加载layout.phtml和index.phtml。

我相信我误解了一般如何使用ServiceManager或可能的ZF2的基本部分,并且非常感谢任何人都可以提供的任何见解。这也是我在StackOverflow上的第一个问题,所以我欢迎任何关于格式化我的问题的建议。感谢。

3 个答案:

答案 0 :(得分:3)

从服务经理那里获得工厂有两个很好的选择。一个是工厂类的创建,它大多发生在Zend Framework代码本身。第二个就是使用闭包,正如你所做的那样。

确保您不输入以下内容:

'test-model' => Dashboard\Model\TestModel(),

但是像你的第一个真正的封闭就是一个很好的例子。其次,当您尝试获取无法实例化的服务时,Service Manager始终会发出异常。请注意,此异常不包括以下消息:在实例化期间可能找不到类或抛出异常(例如,因为服务管理器无法实例化您尝试获取的服务的依赖关系)。

最后一点是您不需要在您尝试获取的位置导入带有use语句的FQCN(完全限定类名)。但是,当您尝试实例化时,需要导入FQCN。

这样可行:

<?php

class MyClass
{
  protected $sm;

  public function setServiceManager($sm)
  {
    $this->sm = $sm;
  }

  public function doSomething()
  {
    $this->sm->get('some-special-key');
  }
}

这也是:

<?php

use Foo\Bar\Baz;

$serviceConfig = array(
  'factories' => array(
    'some-special-key' => function($sm) {
      return new Baz;
    }
  ),
);

但这不是(如果你试图获得Foo\Bar\Baz):

<?php

$serviceConfig = array(
  'factories' => array(
    'some-special-key' => function($sm) {
      return new Baz;
    }
  ),
);

您可能想要查看我的SlmCmfKernel存储库。在我的Module.php中,我添加了一个服务配置文件,该文件放在separate location中。在another part of the code我从经理处获得了一项服务。

答案 1 :(得分:2)

只是为了澄清:

public function getServiceConfiguration()
{
    return array(
        'factories' => array(
            'test-model' => function($sm){
                return new Model\TestModel;
            },
        ),
    );
}

也可以写为invokable:

public function getServiceConfiguration()
{
    return array(
        'invokables' => array(
            'test-model' => 'Model\TestModel',
        ),
    );
}

在这种情况下,您可能需要考虑在配置文件而不是Module.php中定义它,因为您可以利用配置缓存,因为它只是一个标量数组。

答案 2 :(得分:1)

我最后通过更多的调试找到了我自己问题的答案(我以前没有ini_set('display_errors','1'); set - 傻傻的我。)

将类添加到ZF2 ServiceManager(在Module.php中)的正确语法似乎是:

public function getServiceConfiguration()
{
    return array(
        'factories' => array(
            'album-table' => function($sm) {
                $dbAdapter = $sm->get('db-adapter');
                $table = new AlbumTable($dbAdapter);
                return $table;
            },
            'test-model' => function($sm){
                return new Model\TestModel;
            },
        ),
    );
}

只是为了完整性,为了从你所包含的类中调用一个方法,你可以在你的控制器文件中使用它(在我的例子中是DashboardController.php),只要你扩展ActionController类:

class DashboardController extends ActionController
{
    public function indexAction()
    {   
        return new ViewModel(array(
            'users' => $this->getTestModel()->testMethod(),
        ));
    }

    public function getTestModel()
    {
        if (!$this->testModel) {
            $sm = $this->getServiceLocator();
            $this->testModel = $sm->get('test-model');
        }
        return $this->testModel;
    }

}

其中testMethod()是TestModel类中的方法。对于任何刚接触Zend或命名空间的人来说,有一些注意事项 - 我的一个问题是,当我将文件顶部的命名空间设置为Dashboard时,我正在使用完整的类名引用(Dashboard \ Model \ TestModel),所以第一个仪表板是不必要的,并导致PHP查找Dashboard \ Dashboard \ Model \ TestModel。此外,在撰写本文时,样本ZF2模块很少 - 我建议您查看EvanDotPro的ZfcUser等样本,以获取此类事件的示例。

我最初对用于向ServiceManager添加类的各种子键的困惑仍然存在,所以如果您对此有任何见解,我将继续监视此问题并将您的答案标记为“答案”解决这个问题,谢谢你:)。