ZF2服务定位器(ZF2 Service Locator)

2019-08-05 17:17发布

我是很新的ZF2,我用它进行试验。 我有一个视图助手,我需要它来访问表对象。 在我的控制,我可以运行:

$this->getServiceLocator();

但理想我想我的视图助手中运行这些。 不幸的是,我似乎无法从我的观点助手里访问它。 我试图通过它通过构造,在module.config.php配置工厂方法,但是当我尝试,Zend公司将不再传递一个tablegateway对象到从模块的模块服务工厂方法创建了模型对象之一。 PHP文件。 这似乎是因为它不再调用工厂方法,并选择使不带任何参数实例化运行。

我不能肯定我明白为什么认为工厂方法会影响到一组不同的工厂方法有不同的名称。

谁能告诉我什么是错的我在做什么? 我可以提供更多的细节,但在这一点上,我什么细节,而无需提供整个代码库实际上重要不清楚。

谢谢。

Answer 1:

酥确实提供了一个有效的回答你的问题,但我会建议把它一步。 服务定位器的喷射使你的视图助手紧密耦合到框架和服务定位器模式和脆弱,因为你的应用内每一段代码可以在服务定位器修改每个服务。

有是有原因直接注入你的依赖 ,所以你只能依靠你的依赖,你就不再实施这一反模式。 让我们假设你的视图助手取决于MyModule\Model\MyTable ,那么你的视图助手只是看起来像这样的构造函数:

namespace MyModule;

use MyModule\Model\MyTable;
use Zend\View\Helper\AbstractHelper;

class MyViewHelper extends AbstractHelper
{
  protected $table;

  public function __construct(MyTable $table)
  {
    $this->table = $table;
  }
}

正如你指出,你只要注入你的MyTable现在:

namespace MyModule;

class Module
{
  public function getViewHelperConfig()
  {
    return array(
      'factories' => array(
        'MyViewHelper' => function($sm) {
          $sm = $sm->getServiceLocator(); // $sm was the view helper's locator
          $table = $sm->get('MyModule_MyTable');

          $helper = new MyModule\View\Helper\MyHelper($table);
          return $helper;
        }
      )
    );
  }
}

需要注意的是一个视图助手工厂内服务管理器是视图助手的服务经理没有(也看到了“主”一个在表格为注册的博客中我之前写的 )。 在$sm->getServiceLocator()解决了这个给你。

我不能肯定我明白为什么认为工厂方法会影响到一组不同的工厂方法有不同的名称。

它不是,那么有可能是在你的代码中的bug。 如果上述方法无效,请提供你的服务管理器配置一些更多的细节,所以我可以更新我的答案。

其中一个上述方法的一大优点是你做单元测试很容易为你的视图助手。 你可以嘲笑表网关和专注于您的视图助手的完整行为。

use MyModule\View\Helper\MyHelper;

public function testHelperusesTable
{
  $mock   = $this->getMock('MyModule\Model\MyTable');
  $helper = new MyHelper($mock);

  // Test your $helper now
}


Answer 2:

你可以注入的服务定位成从Module.php视图助手配置你的视图助手

// Application/Module.php

public function getViewHelperConfig()
{
    return array(
        'factories' => array(
            'myViewHelper' => function ($serviceManager) {
                // Get the service locator 
                $serviceLocator = $serviceManager->getServiceLocator();
                // pass it to your helper 
                return new \Application\View\Helper\MyViewHelper($serviceLocator);
            }
        )
    );
}

在您的视图助手

<?php
namespace Application\View\Helper;

use Zend\View\Helper\AbstractHelper,
    Zend\ServiceManager\ServiceLocatorInterface as ServiceLocator;

class MyViewHelper extends AbstractHelper
{
    protected $serviceLocator;

    public function __construct(ServiceLocator $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
    }
}


Answer 3:

虽然Zend框架的工作中,我们常常需要定制的帮手,让我们的工作变得容易,在ZF1从助手访问数据库模型是很容易的,但我被困该如何访问数据库模型中的自定义视图助手任何表,但因为我是需要它,我绕过通过视图creatina新的数据库适配器对象,这是从来没有好办法在不专业的方式问题,但最近我都挺过来了非常有趣的方式来知道要访问数据库适配器视图助手,并在那里,我有执行任何表的任何查询,则可能不是这样的Zend F2的方式,但非常简单和短期的方式来解决这个问题。

这里是我的模型示例...

<?php

namespace Application\Model;

use Zend\Db\TableGateway\TableGateway;

class SlideImageSubTable {

    protected $tableGateway;
    public $adapter;

    public function __construct(TableGateway $tableGateway) {
        $this->tableGateway = $tableGateway;
        $this->adapter = $this->tableGateway->getAdapter();
    }

    public function fetchAll() {
        $resultSet = $this->tableGateway->select();
        return $resultSet;
    }

    public function getSlideImageSub($id) {
        $id = (int) $id;
        $rowset = $this->tableGateway->select(array('id' => $id));
        $row = $rowset->current();
        if (!$row) {
            throw new \Exception("Could not find row $id");
        }
        return $row;
    }

    public function getImageMenu($id) {
        $id = (int) $id;
        $rowset = $this->tableGateway->select(array('slide_image_id' => $id));
        $rows = array_values(iterator_to_array($rowset));
        if (!$rows) {
            throw new \Exception("Could not find row $id");
        }
        return $rows;
    }

    public function saveSlideImageSub(SlideImageSub $slideImageSub) {
        $data = array(
            'slide_image_id' => $slideImageSub->slide_image_id,
            'title' => $slideImageSub->title,
            'description' => $slideImageSub->description
        );

        $id = (int) $slideImageSub->id;
        if ($id == 0) {
            $this->tableGateway->insert($data);
        } else {
            if ($this->getSlideImageSub($id)) {
                $this->tableGateway->update($data, array('id' => $id));
            } else {
                throw new \Exception('Form id does not exist');
            }
        }
    }

    public function deleteSlideImageSub($id) {
        $this->tableGateway->delete(array('id' => $id));
    }

}

试想一下,在“公共$适配器”公共变量。 并在构造我要去通过调用$这个 - > tableGateway-> getAdapter()来初始化; 方法,getAdapter()是可用的thorugh网关对象。

然后在我的控制器动作来看,我必须把它分配给任何变量,并通过该变量来查看页面。 像这样..

public function equitiesAction() {
        $image_id = $this->params('id');
        $result = $this->getTable('SlideImageSub')->getImageMenu($image_id);
        $adapter = $this->table->adapter;
        $view = new ViewModel(array(
                    'result' => $result,
                    'adapter' => $adapter,
                ));
        return $view;
    }

并在视图我通过“适配器”对象这样的自定义视图..

<?php echo $this->GetMenuProducts( $this->adapter); ?>

现在,在自定义视图,我可以使用这个数据库适配器对象和任何表创建选择查询。

希望这将帮助别人,我环顾四周在自定义视图助手使用的数据库访问,但所提供的配置方法,并没有为我工作。

谢谢



Answer 4:

$this->getView()->getHelperPluginManager()->getServiceLocator();


文章来源: ZF2 Service Locator