7.13. 从以前的版本移植

随着时间的推移,MVC组件的API修改了许多。如果你从Zend Framework早期的版本开始使用,遵照下面的方针来移植你的脚本来使用新的架构。

7.13.1.  从 0.9.3 到 1.0.0RC1 或更新的版本的移植

在1.0.0RC1中的主要变化是ErrorHandler插件的缺省激活 和 ViewRenderer的动作助手的简介。请阅读整个的文档来看它们是如何工作的和对你的应用程序有什么影响。

postDispatch()期间,ErrorHandler插件检查异常,并转发到一个特定的错误管理控制器。你需要包含这样一个控制器在你的程序中,可以通过设置前端控制器参数noErrorHandler来禁止它:


<?php
$front
->setParam('noErrorHandler'true);

基于当前版本,ViewRenderer动作助手使视图注入到动作控制器和视图脚本的自动调用自动化。你可能遇到的主要问题是如果你有没有调用视图脚本的动作并且不转发也不重定向,因为ViewRenderer将基于动作名来尝试调用一个视图脚本。

有若干策略你可以用来更新你的代码。短期,你可以在派遣之前全局地在前端控制器引导文件禁止ViewRenderer


<?php
// Assuming $front is an instance of Zend_Controller_Front
$front->setParam('noViewRenderer'true);

然而,这不是一个好的长期策略,因为它意味着最大可能你要写更多的代码。

当你准备好开始使用ViewRenderer功能,有若干事情需要在控制器代码里寻找。首先,看看动作方法(以'Action'结尾的方法)都在干什么。如果下面任何事情都没有发生,你需要修改:

  • Calls to $this->render()

  • Calls to $this->_forward()

  • Calls to $this->_redirect()

  • Calls to the Redirector action helper

最容易的修改就是为那个方法禁止auto-rendering:


$this->_helper->viewRenderer->setNoRender();

如果你发现没有动作方法调用,转发或重定向,你可能需要把上面一行放到preDispatch()init()方法:


public function preDispatch()
{
    // disable view script autorendering
    $this->_helper->viewRenderer->setNoRender()
    // .. do other things...
}

如果你调用render()并使用传统模块目录结构,你将想修改你的代码去利用自动调用:

  • 如果在一个单个的动作里调用多个视图脚本,你不需要修改任何事情。

  • 如果不带参数调用render(),你可以删除它。

  • 如果带参数调用render(),并以后不做任何处理或调用多个视图脚本,你可以修改这些调用去读$this->_helper->viewRenderer()

如果你不使用传统模块目录结构,有很多方法来设置视图基本路径和脚本路径参数,这样你可以使用ViewRenderer。请阅读ViewRenderer 文档中关于这些方法的信息。

如果你使用注册表中的视图对象,或定制你的视图对象,或使用不同的视图实现,你需要注入ViewRenderer。这很容易地在任何时候完成。

  • 在派遣前端控制器实例之前:

    
    <?php
    // Assuming $view has already been defined
    $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
    Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
  • 在引导过程中的任何时候:

    
    <?php
    $viewRenderer 
    Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
    $viewRenderer->setView($view);

有许多办法来修改ViewRenderer,包括设置不同的视图脚本来调用,给所有视图脚本路径(包括后缀)可替换元素指定替代,选择响应指定的段来利用,等等。如果你不使用传统模块目录结构,你甚至可以用ViewRenderer联合不同的路径规范。

我们鼓励你用ErrorHandlerViewRenderer改编你的代码,因为它们现在是核心功能。

7.13.2. 从 0.9.2 移植到 0.9.3 或更新的版本

0.9.3 介绍了action helpers。作为这个改变的一部分,下面的方法已经删除因为它们现在被封装到重定向动作助手

  • setRedirectCode();使用 Zend_Controller_Action_Helper_Redirector::setCode()

  • setRedirectPrependBase();使用 Zend_Controller_Action_Helper_Redirector::setPrependBase()

  • setRedirectExit();使用 Zend_Controller_Action_Helper_Redirector::setExit()

阅读动作助手文档有更多的信息关于如何获取和操作助手对象,还有重定向助手文档有更多信息关于设置重定向选项(还有重定向的替代方法)。

7.13.3. 从 0.6.0 移植到 0.8.0 或更新的版本

每次修改,MVC组件的最基本用法保持不变:


require_once 'Zend/Controller/Front.php';
Zend_Controller_Front::run('/path/to/controllers');

然而,目录结构经历了检查,数个组件被删除,同时若干个其它的被改名或添加。变化包括:

  • Zend_Controller_Router 被删除有利于rewrite路由器。

  • Zend_Controller_RewriteRouter 改名为 Zend_Controller_Router_Rewrite,并提升为标准路由器和框架一起发行;如果没有提供其它路由器 Zend_Controller_Front 将使用它为缺省的路由器。

  • 使用rewrite路由器的新路由被引入,Zend_Controller_Router_Route_Module;它覆盖了MVC使用的缺省路由,并支持控制器模块

  • Zend_Controller_Router_StaticRoute 改名为 Zend_Controller_Router_Route_Static

  • Zend_Controller_Dispatcher 改名为 Zend_Controller_Dispatcher_Standard

  • Zend_Controller_Action::_forward()的参数被修改。签名现在是:

    
    final protected function _forward($action, $controller = null, $module = null, array $params = null);
    

    $action总是被要求的;如果没有指定控制器,在当前控制器中的动作被使用。$module 总是被忽略除非 $controller 被指定。最后,任何提供的$params 将被追加到请求对象。如果你不请求控制器或模块,当仍需要传递参数,简单地指定null到这些值。

7.13.4. 从 0.2.0 或以前的版本移植到 0.6.0

(这段就让它保持原样吧 Jason Qi)

The most basic usage of the MVC components has not changed; you can still do each of the following:


require_once 'Zend/Controller/Front.php';
Zend_Controller_Front::run('/path/to/controllers');

/* -- create a router -- */
$router = new Zend_Controller_RewriteRouter();
$router->addRoute('user', 'user/:username', array('controller' => 'user',
'action' => 'info'));

/* -- set it in a controller -- */
$ctrl = Zend_Controller_Front::getInstance();
$ctrl->setRouter($router);

/* -- set controller directory and dispatch -- */
$ctrl->setControllerDirectory('/path/to/controllers');
$ctrl->dispatch();

We encourage use of the Response object to aggregate content and headers. This will allow for more flexible output format switching (for instance, JSON or XML instead of XHTML) in your applications. By default, dispatch() will render the response, sending both headers and rendering any content. You may also have the front controller return the response using returnResponse(), and then render the response using your own logic. A future version of the front controller may enforce use of the response object via output buffering.

There are many additional features that extend the existing API, and these are noted in the documentation.

The main changes you will need to be aware of will be found when subclassing the various components. Key amongst these are:

  • Zend_Controller_Front::dispatch() by default traps exceptions in the response object, and does not render them, in order to prevent sensitive system information from being rendered. You can override this in several ways:

    • Set throwExceptions() in the front controller:

      
      $front->throwExceptions(true);
      
    • Set renderExceptions() in the response object:

      
      $response->renderExceptions(true);
      $front->setResponse($response);
      $front->dispatch();

      // or:
      $front->returnResponse(true);
      $response = $front->dispatch();
      $response->renderExceptions(true);
      echo $response;
  • Zend_Controller_Dispatcher_Interface::dispatch() now accepts and returns a 第 7.4 节 “请求对象” object instead of a dispatcher token.

  • Zend_Controller_Router_Interface::route() now accepts and returns a 第 7.4 节 “请求对象” object instead of a dispatcher token.

  • Zend_Controller_Action changes include:

    • The constructor now accepts exactly three arguments, Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, and array $params (optional). Zend_Controller_Action::__construct() uses these to set the request, response, and invokeArgs properties of the object, and if overriding the constructor, you should do so as well. Better yet, use the init() method to do any instance configuration, as this method is called as the final action of the constructor.

    • run() is no longer defined as final, but is also no longer used by the front controller; it's sole purpose is for using the class as a page controller. It now takes two optional arguments, a Zend_Controller_Request_Abstract $request and a Zend_Controller_Response_Abstract $response.

    • indexAction() no longer needs to be defined, but is encouraged as the default action. This allows using the RewriteRouter and action controllers to specify different default action methods.

    • __call() should be overridden to handle any undefined actions automatically.

    • _redirect() now takes an optional second argument, the HTTP code to return with the redirect, and an optional third argument, $prependBase, that can indicate that the base URL registered with the request object should be prepended to the url specified.

    • The _action property is no longer set. This property was a Zend_Controller_Dispatcher_Token, which no longer exists in the current incarnation. The sole purpose of the token was to provide information about the requested controller, action, and URL parameters. This information is now available in the request object, and can be accessed as follows:

      
      // Retrieve the requested controller name
      // Access used to be via: $this->_action->getControllerName().
      // The example below uses getRequest(), though you may also directly access the
      // $_request property; using getRequest() is recommended as a parent class may
      // override access to the request object.
      $controller = $this->getRequest()->getControllerName();

      // Retrieve the requested action name
      // Access used to be via: $this->_action->getActionName().
      $action = $this->getRequest()->getActionName();

      // Retrieve the request parameters
      // This hasn't changed; the _getParams() and _getParam() methods simply proxy to
      // the request object now.
      $params = $this->_getParams();
      $foo = $this->_getParam('foo', 'default'); // request 'foo' parameter, using
                                                 // 'default' as default value if not found
    • noRouteAction() has been removed. The appropriate way to handle non-existent action methods should you wish to route them to a default action is using __call():

      
      public function __call($method, $args)
      {
          // If an unmatched 'Action' method was requested, pass on to the default
          // action method:
          if ('Action' == substr($method, -6)) {
              return $this->defaultAction();
          }

          throw new Zend_Controller_Exception('Invalid method called');
      }
  • Zend_Controller_RewriteRouter::setRewriteBase() has been removed. Use Zend_Controller_Front::setBaseUrl() instead (or Zend_Controller_Request_Http::setBaseUrl(), if using that request class).

  • Zend_Controller_Plugin_Interface was replaced by Zend_Controller_Plugin_Abstract. All methods now accept and return a 第 7.4 节 “请求对象” object instead of a dispatcher token.