千家信息网

Zend Framework之动作基类Zend_Controller_Action的示例分析

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,这篇文章主要为大家展示了"Zend Framework之动作基类Zend_Controller_Action的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并
千家信息网最后更新 2026年10月31日Zend Framework之动作基类Zend_Controller_Action的示例分析

这篇文章主要为大家展示了"Zend Framework之动作基类Zend_Controller_Action的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Zend Framework之动作基类Zend_Controller_Action的示例分析"这篇文章吧。

具体如下:

Zend_Controller_Action的实现

Zend Framework的动作控制器需要继承Zend_Controller_Action,Zend_Controller_Action提供了动作控制器的基本功能,具体参考如下代码:

Zend_Controller_Action_Interface

Zend_Controller_Action

setRequest($request)       ->setResponse($response)       ->_setInvokeArgs($invokeArgs);    $this->_helper = new Zend_Controller_Action_HelperBroker($this);    $this->init();  }  public function init()  {  }  public function initView()  {    if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) {      return $this->view;    }    require_once 'Zend/View/Interface.php';    if (isset($this->view) && ($this->view instanceof Zend_View_Interface)) {      return $this->view;    }    $request = $this->getRequest();    $module = $request->getModuleName();    $dirs  = $this->getFrontController()->getControllerDirectory();    if (empty($module) || !isset($dirs[$module])) {      $module = $this->getFrontController()->getDispatcher()->getDefaultModule();    }    $baseDir = dirname($dirs[$module]) . DIRECTORY_SEPARATOR . 'views';    if (!file_exists($baseDir) || !is_dir($baseDir)) {      require_once 'Zend/Controller/Exception.php';      throw new Zend_Controller_Exception('Missing base view directory ("' . $baseDir . '")');    }    require_once 'Zend/View.php';    $this->view = new Zend_View(array('basePath' => $baseDir));    return $this->view;  }  public function render($action = null, $name = null, $noController = false)  {    if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) {      return $this->_helper->viewRenderer->render($action, $name, $noController);    }    $view  = $this->initView();    $script = $this->getViewScript($action, $noController);    $this->getResponse()->appendBody(      $view->render($script),      $name    );  }  public function renderScript($script, $name = null)  {    if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) {      return $this->_helper->viewRenderer->renderScript($script, $name);    }    $view = $this->initView();    $this->getResponse()->appendBody(      $view->render($script),      $name    );  }  public function getViewScript($action = null, $noController = null)  {    if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) {      $viewRenderer = $this->_helper->getHelper('viewRenderer');      if (null !== $noController) {        $viewRenderer->setNoController($noController);      }      return $viewRenderer->getViewScript($action);    }    $request = $this->getRequest();    if (null === $action) {      $action = $request->getActionName();    } elseif (!is_string($action)) {      require_once 'Zend/Controller/Exception.php';      throw new Zend_Controller_Exception('Invalid action specifier for view render');    }    if (null === $this->_delimiters) {      $dispatcher = Zend_Controller_Front::getInstance()->getDispatcher();      $wordDelimiters = $dispatcher->getWordDelimiter();      $pathDelimiters = $dispatcher->getPathDelimiter();      $this->_delimiters = array_unique(array_merge($wordDelimiters, (array) $pathDelimiters));    }    $action = str_replace($this->_delimiters, '-', $action);    $script = $action . '.' . $this->viewSuffix;    if (!$noController) {      $controller = $request->getControllerName();      $controller = str_replace($this->_delimiters, '-', $controller);      $script = $controller . DIRECTORY_SEPARATOR . $script;    }    return $script;  }  public function getRequest()  {    return $this->_request;  }  public function setRequest(Zend_Controller_Request_Abstract $request)  {    $this->_request = $request;    return $this;  }  public function getResponse()  {    return $this->_response;  }  public function setResponse(Zend_Controller_Response_Abstract $response)  {    $this->_response = $response;    return $this;  }  protected function _setInvokeArgs(array $args = array())  {    $this->_invokeArgs = $args;    return $this;  }  public function getInvokeArgs()  {    return $this->_invokeArgs;  }  public function getInvokeArg($key)  {    if (isset($this->_invokeArgs[$key])) {      return $this->_invokeArgs[$key];    }    return null;  }  public function getHelper($helperName)  {    return $this->_helper->{$helperName};  }  public function getHelperCopy($helperName)  {    return clone $this->_helper->{$helperName};  }  public function setFrontController(Zend_Controller_Front $front)  {    $this->_frontController = $front;    return $this;  }  public function getFrontController()  {    // Used cache version if found    if (null !== $this->_frontController) {      return $this->_frontController;    }    // Grab singleton instance, if class has been loaded    if (class_exists('Zend_Controller_Front')) {      $this->_frontController = Zend_Controller_Front::getInstance();      return $this->_frontController;    }    // Throw exception in all other cases    require_once 'Zend/Controller/Exception.php';    throw new Zend_Controller_Exception('Front controller class has not been loaded');  }  public function preDispatch()  {  }  public function postDispatch()  {  }  public function __call($methodName, $args)  {    require_once 'Zend/Controller/Action/Exception.php';    if ('Action' == substr($methodName, -6)) {      $action = substr($methodName, 0, strlen($methodName) - 6);      throw new Zend_Controller_Action_Exception(sprintf('Action "%s" does not exist and was not trapped in __call()', $action), 404);    }    throw new Zend_Controller_Action_Exception(sprintf('Method "%s" does not exist and was not trapped in __call()', $methodName), 500);  }  public function dispatch($action)  {    // Notify helpers of action preDispatch state    $this->_helper->notifyPreDispatch();    $this->preDispatch();    if ($this->getRequest()->isDispatched()) {      if (null === $this->_classMethods) {        $this->_classMethods = get_class_methods($this);      }      // If pre-dispatch hooks introduced a redirect then stop dispatch      // @see ZF-7496      if (!($this->getResponse()->isRedirect())) {        // preDispatch() didn't change the action, so we can continue        if ($this->getInvokeArg('useCaseSensitiveActions') || in_array($action, $this->_classMethods)) {          if ($this->getInvokeArg('useCaseSensitiveActions')) {            trigger_error('Using case sensitive actions without word separators is deprecated; please do not rely on this "feature"');          }          $this->$action();        } else {          $this->__call($action, array());        }      }      $this->postDispatch();    }    // whats actually important here is that this action controller is    // shutting down, regardless of dispatching; notify the helpers of this    // state    $this->_helper->notifyPostDispatch();  }  public function run(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null)  {    if (null !== $request) {      $this->setRequest($request);    } else {      $request = $this->getRequest();    }    if (null !== $response) {      $this->setResponse($response);    }    $action = $request->getActionName();    if (empty($action)) {      $action = 'index';    }    $action = $action . 'Action';    $request->setDispatched(true);    $this->dispatch($action);    return $this->getResponse();  }  protected function _getParam($paramName, $default = null)  {    $value = $this->getRequest()->getParam($paramName);     if ((null === $value || '' === $value) && (null !== $default)) {      $value = $default;    }    return $value;  }  protected function _setParam($paramName, $value)  {    $this->getRequest()->setParam($paramName, $value);    return $this;  }  protected function _hasParam($paramName)  {    return null !== $this->getRequest()->getParam($paramName);  }  protected function _getAllParams()  {    return $this->getRequest()->getParams();  }  final protected function _forward($action, $controller = null, $module = null, array $params = null)  {    $request = $this->getRequest();    if (null !== $params) {      $request->setParams($params);    }    if (null !== $controller) {      $request->setControllerName($controller);      // Module should only be reset if controller has been specified      if (null !== $module) {        $request->setModuleName($module);      }    }    $request->setActionName($action)        ->setDispatched(false);  }  protected function _redirect($url, array $options = array())  {    $this->_helper->redirector->gotoUrl($url, $options);  }}

Zend_Controller_Action提供了动作和视图的render功能,以及注册请求和响应对象,常用助手等等。

动作控制器的常用方法

在动作控制器中常用的方法和属性如下:

$this->_helper主要完成助手的相关操作例如:

// 只是局部控制器;当初始化加载时,对这个控制器的所有动作有效:$this->_helper->viewRenderer->setNoRender(true);// 全局:$this->_helper->removeHelper('viewRenderer'); // 也是全局,但需要和本地版本协作,以便繁殖这个控制器:Zend_Controller_Front::getInstance()->setParam('noViewRenderer', true);

通过设置ViewRenderer的noRender标记,可以简单地为一个独立的视图禁止解析(rendering):

class FooController extends Zend_Controller_Action{  public function barAction()  {    // disable autorendering for this action only:    $this->_helper->viewRenderer->setNoRender();  }}

禁止ViewRenderer的主要原因是如果你不需要视图对象或者如果你不通过视图脚本(例如,当使用动作控制器来司服网站服务协议如SOAP,XML-RPC或REST)来解析。大多数情况下,你不需要全局地禁止ViewRenderer,只选择性地在个别控制器或动作里禁止它。

请求对象和响应对象的相关操作

无数的对象和变量与对象一起注册,并且每个都有访问器方法。

请求对象:getRequest()可用来读取调用动作请求对象。

响应对象: getResponse()可用来读取收集最终响应的响应对象。一些典型的调用看起来象这样:

$this->getResponse()->setHeader('Content-Type', 'text/xml');$this->getResponse()->appendBody($content);

调用参数:前端控制器可能把参数传给路由器、派遣器和动作控制器。为了读取这些参数,可使用getInvokeArg($key);另外,用getInvokeArgs()读取整个参数列表。

请求参数:请求对象手机请求参数,如任何_GET 或 _POST 参数,或者指定在URL的路径信息里的用户参数。为了读取这些参数,可使用_getParam($key)或_getAllParams()。也可以用_setParam()来设置请求参数;当转发到另外的动作时这很有用。

用_hasParam($key)来测试是否一个参数存在(对逻辑分支有用)。

Note: _getParam()可带有一个可选的第二个参数,如果它不是空的,就包含一个缺省的值。用它在读取值之前来消除对_hasParam() 的调用:

// Use default value of 1 if id is not set$id = $this->_getParam('id', 1);// Instead of:if ($this->_hasParam('id') {  $id = $this->_getParam('id');} else {  $id = 1;}

视图的相关操作

Zend_Controller_Action为视图继承提供了一个初步的灵活的机制。有两个方法来完成这个:initView() 和 render();前者松散地加载$view public 属性,后者基于当前请求的动作来解析视图,它们使用目录层次来决定脚本路径。

视图初始化

initView()初始化视图对象。为了读取视图对象,render()调用initView(),但它可以在任何时候被初始化;缺省地,它用Zend_View对象来组装$view属性,但任何实现Zend_View_Interface的类可以使用。如果$view已经被初始化,它就简单地返回属性。

缺省的实现使用下面假设的目录结构:

applicationOrModule/
controllers/
IndexController.php
views/
scripts/
index/
index.phtml
helpers/
filters/

换句话说,视图脚本假定放在views/scripts/子目录,同时假定 views子目录还包含兄弟功能(助手和过滤器)。确定视图脚本名称和路径时,先以 views/scripts/作为基路径,然后加上以视图脚本对应控制器命名的目录。

解析(Rendering)视图

render() 有下列特征:has the following signature:

string render(string $action = null,       string $name = null,       bool $noController = false);

render()解析视图脚本。如果没有传递参数,它假定请求的脚本是[controller]/[action].phtml (.phtml是$viewSuffix属性的值)。为$action传递一个值将解析在[controller]子目录中的模板。为用[controller]重写,传递一个true值给$noController。最后,模板被解析到响应对象;如果你希望解析到一个在响应对象里指定的named segment,传递一个值给$name。

Note: 因为控制器和动作名字里可能包含分隔符如'_'、 '.' 和 '-',当决定视图名字时,render()把它们规格化成 '-'.在内部,它使用派遣器的字和路径分隔符来做规格化。这样,对/foo.bar/baz-bat的请求将解析脚本foo-bar/baz-bat.phtml。如果动作方法包含camelCasing,记住当决定视图脚本文件名的时候,这将变成由'-'分隔的字。

一些例子:

class MyController extends Zend_Controller_Action{  public function fooAction()  {    // Renders my/foo.phtml    $this->render();    // Renders my/bar.phtml    $this->render('bar');    // Renders baz.phtml    $this->render('baz', null, true);    // Renders my/login.phtml to the 'form' segment of the    // response object    $this->render('login', 'form');    // Renders site.phtml to the 'page' segment of the response    // object; does not use the 'my/' subirectory    $this->render('site', 'page', true);  }  public function bazBatAction()  {    // Renders my/baz-bat.phtml    $this->render();  }}

其它

_forward($action, $controller = null, $module = null, array $params = null) :执行另外一个动作。如果在preDispatch()里调用,当前请求的动作将被跳过来支持新的动作。否则,在当前动作被处理之后,在_forward()请求的动作将被执行。

_redirect($url, array $options = array()):重定向到另外一个地方。这个方法用URL和一组可选的选项。缺省地,它执行HTTP 302 重定向。

选项可包括一个或多个下面这些:

exit:是否立即退出。如果被请求,它将干净地关闭任何打开的会话和执行重定向。

可以用setRedirectExit()访问器在控制器里全局地设置这个选项。

prependBase:是否预先考虑基础URL和URL提供的请求对象一起注册。

使用setRedirectPrependBase()访问器,在控制器里全局地设置这个选项。

code:在重定向时要用什么HTTP代码。缺省使用302;可以用从301到306之间的任何代码。

使用setRedirectCode()访问器,在控制器里全局地设置这个选项。

扩展自定义Zend_Controller_Action

为了创建动作控制器,设计上,Zend_Controller_Action 必须被继承。至少,需要定义控制器可能调用的动作方法。

除了为web应用程序创建有用的函数外,你可能发现在不同的控制器里重复同样的设置和实用方法;如果这样,创建一个继承(extends)Zend_Controller_Action 的基础类可能会解决问题。

Example #1 如何处理不存在的动作

如果控制器的请求包括一个未定义的动作方法,Zend_Controller_Action::__call()将被调用。__call()当然是PHP中用来重载方法的魔术方法。

缺省地,这个方法抛出一个Zend_Controller_Action_Exception 来表明在控制器里没有发现要求的方法。如果要求的方法以'Action'结尾,就假设一个动作被请求并且不存在;这样的错误导致带有代码为 404 的异常。所有其它方法导致带有代码为 500 的异常。这使你很容易地在错误句柄里区分是页面没有发现还是程序错误。

如果想执行其它操作,你应该重写这个函数。例如,如果你想显示错误信息,可以象下面这样来写:

class MyController extends Zend_Controller_Action{  public function __call($method, $args)  {    if ('Action' == substr($method, -6)) {      // If the action method was not found, render the error      // template      return $this->render('error');    }    // all other methods throw an exception    throw new Exception('Invalid method "'              . $method              . '" called',              500);  }}

另外的可能性就是你可能想转发到缺省控制页面:

class MyController extends Zend_Controller_Action{  public function indexAction()  {    $this->render();  }  public function __call($method, $args)  {    if ('Action' == substr($method, -6)) {      // If the action method was not found, forward to the      // index action      return $this->_forward('index');    }    // all other methods throw an exception    throw new Exception('Invalid method "'              . $method              . '" called',              500);  }}

为了定制控制器,除了重写__call()以外,本章前面说涉及的初始化、实用程序、访问器、视图和派遣钩子等方法都可以被重写。作为例子,如果把视图对象保存到注册表里,你可能想用象下面的代码来修改initView():

abstract class My_Base_Controller extends Zend_Controller_Action{  public function initView()  {    if (null === $this->view) {      if (Zend_Registry::isRegistered('view')) {        $this->view = Zend_Registry::get('view');      } else {        $this->view = new Zend_View();        $this->view->setBasePath(dirname(__FILE__) . '/../views');      }    }    return $this->view;  }}

以上是"Zend Framework之动作基类Zend_Controller_Action的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

动作 控制 控制器 视图 对象 方法 参数 脚本 代码 全局 属性 路径 错误 示例 分析 内容 功能 助手 子目 子目录 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 广东万易互联网科技有限公司惠州分公司 为想互联网科技怎么样 A股互联网金融科技公司 新华互联网科技学院 互联网科技卖菜 网络科技有限互联网 善班互联网科技有限公司 互联网科技大会案例 美国互联网前沿科技 湖南洣水互联网科技有限公司扣款 南山科技园互联网公司有哪些 成都铂石互联网科技做什么的 青海科技产业互联网发展 亳州好赞互联网科技有限公司 翼展科技 首家互联网医院 山东有哪些互联网科技公司 伍佰万互联网科技怎么赚钱 互联网科技实习生岗位 富国互联网科技002692 广东猫王互联网科技有限公司电话 北京互联网科技公司 亿策互联网科技 唐信互联网科技 大连 中化能源互联网科技招聘 互联网行业科技股 互联网科技的全部知识 厦门江牛科技互联网 互联网科技包装股 九思连强互联网电子科技有限公司 北京品多多互联网科技有限公司
0