Zend Framework - 如何解决模型构造函数调用的参数 1 上可捕获的致命错误?

Zend Framework - How to resolve catchable fatal error on argument 1 of model constructor invocation?

场景:

在设置 Zend Framework Latest Skeleton App 并在本地 PHP Debugger Tool Eclipse 环境中设置调试后,我在设置我的第一个模型(称为 ActionItem)时遇到了一个问题。根据 Zend Framework 上的说明,我在 Module.php.

中包含了 getServiceConfig()

特定错误

Catchable fatal error: Argument 1 passed to Application\Model\ActionItem::__construct() must be an instance of Zend\Db\TableGateway\TableGateway, none given

分析:

在下面的代码中(Module.php),我的 ActionItem() 构造函数(在第 3 个代码块 Model.php) 没有参数作为 TableGateway 参数传递给它。

Module.php

 public function getServiceConfig()
        {   
             return array(
                 'factories' => array(
                     'Application\Model\ActionItem' =>  function($sm) {
                         $tableGateway = $sm->get('ActionItemTableGateway');
                         $table = new ActionItem($tableGateway);
                         return $table;
                     },
                     'ActionItemTableGateway' => function ($sm) {
                         $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                         $resultSetPrototype = new ResultSet();
                         $resultSetPrototype->setArrayObjectPrototype(new ActionItem());  ###### Here, the ActionItem Constructor is passed nothing causing the fatal error.
                         return new TableGateway('application', $dbAdapter, null, $resultSetPrototype);
                     },
                 ),
             );
        }

控制器 SummaryController.php

namespace Application\Controller;

use Application\Model\ActionItem;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class SummaryController extends AbstractActionController
{
    protected $actionItem;

    public function getActionItem()
    {
        if (!$this->actionItem) {
            $sm = $this->getServiceLocator();
            $this->actionItem = $sm->get('Application\Model\ActionItem');
        }
        return $this->actionItem;
    }

    public function IndexAction()
    {
        return new ViewModel(array (
            'actionitems' => $this->getActionItem()->fetchAll(),    
        ));
        //return new ViewModel();
    }
}

型号ActionItem.php

namespace Application\Model;

    use Zend\Db\TableGateway\TableGateway;

    class ActionItem {
        protected $tableGateway;

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

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

    }

问题

有没有一种方法可以解决这个问题,或者我可以采取多种方法吗?我该怎么做才能解决该错误?

谢谢。

您的 Application\Model\ActionItem 不应引用 TableGateway

您需要将 Application\Model\ActionItem 拆分为服务 class 和真实模型 class。模型 class 应该代表您的业务,但不应该负责存储它自己。

Module.php

public function getServiceConfig()
{
    return array(
        'factories' => array(
            'ActionItemRepository' => function ($sm) {

                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');

                $resultSetPrototype = new HydratingResultSet();
                $resultSetPrototype->setArrayObjectPrototype(new ClassMethods(), new ActionItemEntity());

                $tableGateway = new TableGateway('application', $dbAdapter, null, $resultSetPrototype);

                $service = new ActionItemRepository($tableGateway);
                return $service;
            },
        ),
    );
}

SummaryController.php

使用该服务根据客户端请求与 ActionItem 实体进行交互(获取它们、更新它们、创建它们……)

namespace Application\Controller;

use Application\Service\ActionItemRepository;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class SummaryController extends AbstractActionController
{
    public function IndexAction()
    {
        return new ViewModel(array (
            'actionitems' => $this->getActionItemRepository()->fetchAllByType('pending'),
        ));
    }

    /**
     * @return ActionItemRepository
     */
    private function getActionItemRepository()
    {
        return $this->getServiceLocator()->get('ActionItemRepository');
    }
}

ActionItemEntity

您的实体 class,不依赖于存储层,代表您的业务遵循 classic OOP 原则。

class ActionItemEntity
{
    /**
     * @var DateTime
     */
    protected $myProperty;

    /**
     * @return DateTime
     */
    public function getMyProperty()
    {
        return $this->myProperty;
    }

    /**
     * @param DateTime $myProperty
     */
    public function setMyProperty(DateTime $myProperty)
    {
        $this->myProperty = $myProperty;
    }
}

ActionItemRepository.php

namespace Application\Service;

use Zend\Db\TableGateway\TableGateway;

class ActionItemRepository
{
    /**
     * @var TableGateway
     */
    protected $tableGateway;

    /**
     * @param TableGateway $tableGateway
     */
    public function __construct(TableGateway $tableGateway)
    {
        $this->tableGateway = $tableGateway;
    }

    /**
     * @param string $type
     * @return \Zend\Db\ResultSet\ResultSet
     */
    public function fetchAllByType($type)
    {
        $resultSet = $this->tableGateway->select();

        // @todo: filter on Type

        return $resultSet;
    }

    /**
     * @param ActionItemEntity $actionItem
     */
    public function save(ActionItemEntity $actionItem)
    {
        //@todo
    }
}