3

我对 zf2 很陌生,我正在尝试它。我有一个视图助手,我需要它来访问一个表对象。在我的控制器中,我可以运行:

$this->getServiceLocator();

但理想情况下,我会在我的视图助手中运行它。不幸的是,我似乎无法从我的视图助手中访问它。我尝试通过构造函数传递它,在 module.config.php 中配置一个工厂方法,但是当我尝试这样做时,Zend 将不再将 tablegateway 对象传递给我从模块模块中的服务工厂方法创建的模型对象之一。 .php 文件。这似乎是因为它不再调用工厂方法,而是选择在没有任何参数的情况下运行实例化。

我不确定我是否理解为什么视图工厂方法会影响一组具有不同名称的不同工厂方法。

谁能告诉我我在做什么有什么问题?我可以提供更多细节,但在不提供整个代码库的情况下,我不清楚哪些细节实际上很重要。

谢谢。

4

4 回答 4

7

Crisp 确实为您的问题提供了一个有效的答案,但我建议更进一步。服务定位器的注入使您的视图助手与框架和服务定位器模式紧密耦合并且容易受到攻击,因为应用程序中的每段代码都可以修改服务定位器中的每个服务。

有理由直接注入您的依赖项,因此您只依赖于您的依赖项并且您不再实现此反模式。假设您的视图助手依赖于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()为你解决这个问题。

我不确定我是否理解为什么视图工厂方法会影响一组具有不同名称的不同工厂方法。

不是,因此您的代码中可能存在错误。如果上述方法不起作用,请提供有关您的服务管理器配置的更多详细信息,以便我更新我的答案。

上述方法的一大优点是您可以使视图助手的单元测试变得非常容易。您可以模拟表网关并专注于视图助手的完整行为。

use MyModule\View\Helper\MyHelper;

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

  // Test your $helper now
}
于 2013-01-06T07:48:05.890 回答
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;
    }
}
于 2013-01-05T20:22:09.600 回答
0

在 Zend Framework 中工作时,我们经常需要自定义帮助程序,这使我们的工作变得容易,在 zf1 中从帮助程序访问数据库模型很容易,但我被困在如何访问自定义视图帮助程序中任何表的数据库模型,但就像我一样需要它我通过在视图中创建新的数据库适配器对象以非专业的方式解决问题,这从来都不是好方法,但最近我通过非常有趣的方式了解了在视图助手中访问数据库适配器并且我有对任何表执行任何查询,它可能不是 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));
    }

}

只需查看“public $adapter”公共变量即可。在构造函数中,我将通过调用 $this->tableGateway->getAdapter(); 来初始化它。方法,getAdapter() 通过网关对象可用。

然后在我的控制器操作视图中,我必须将它分配给任何变量并将该变量传递给查看页面。像这样..

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); ?>

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

希望这会对某人有所帮助,我四处寻找在自定义视图助手中使用数据库访问,但提供的配置方法对我不起作用。

谢谢

于 2013-02-28T17:16:37.043 回答
-1
$this->getView()->getHelperPluginManager()->getServiceLocator();
于 2014-05-02T19:27:50.930 回答