이 기사의 예에서는 Zend Framework 튜토리얼에서 Zend_Helpers 작업 도우미 ViewRenderer의 사용법을 설명합니다. 참고하실 수 있도록 모든 사람과 공유하세요. 자세한 내용은 다음과 같습니다.
MVC 구조에서 뷰 레이어와 컨트롤러의 분리 및 렌더링. 반복적이거나 중복되는 작업인 경우가 많습니다. 전체 프레임워크가 MVC를 사용하는 경우 이러한 작업은 합리적으로 설계되어야 합니다. 개발자가 논리적 구조 자체를 제어하기보다는 콘텐츠에 더 집중할 수 있습니다. ZendFramework에서 이 작업은 주로 작업 도우미 ViewRenderer를 통해 수행됩니다. ViewRenderer는 컨트롤러에서 뷰 객체를 설정하고 뷰를 렌더링하는 프로세스를 자동으로 완료합니다.
ViewRenderer
소개
ViewRenderer 어시스턴트는 다음 목표를 달성하도록 설계되었습니다.
컨트롤러 내에서 뷰 객체 인스턴스를 생성할 필요가 없습니다. 뷰 객체는 컨트롤러 내에 자동으로 등록됩니다.
현재 모듈을 기반으로 보기 스크립트, 도우미 및 필터 경로를 자동으로 설정합니다. 도우미 및 필터 클래스의 클래스 이름 접두사에 현재 모듈 이름을 할당합니다.
전달된 모든 컨트롤러 및 작업에 대해 전역적으로 유효한 뷰 개체를 만듭니다.
개발자가 모든 컨트롤러에 대한 기본 보기 해상도 옵션을 설정할 수 있습니다.
개입 없이 자동으로 뷰 스크립트를 구문 분석하는 기능을 추가했습니다.
개발자가 보기 기본 경로 및 보기 스크립트 경로에 대한 자체 사양을 만들 수 있습니다.
참고: _forward(), 리디렉션 또는 렌더링을 수동으로 실행하면 자동 구문 분석이 발생하지 않습니다. 왜냐하면 이러한 작업을 수행하면 ViewRenderer에게 출력 결과를 직접 결정해야 한다고 알려주기 때문입니다.
참고: ViewRenderer Assistant는 기본적으로 활성화되어 있습니다.
프런트 컨트롤러의 noViewRenderer 메소드($front->setParam('noViewRenderer', true))를 통해 매개변수를 설정하거나 헬퍼 브로커 스택(Zend_Controller_Action_HelperBroker::RemoveHelper('viewRenderer')) 및 기타 헬퍼 브로커 스택에서 헬퍼를 제거할 수 있습니다. 도우미를 비활성화하는 방법.
프런트엔드 컨트롤러를 배포하기 전에 ViewRenderer 설정을 수정하려면 다음 두 가지 방법을 사용할 수 있습니다.
인스턴스를 생성하고 자체 ViewRenderer 객체를 등록한 다음 이를 도우미 브로커에 전달합니다.
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer(); $viewRenderer->setView($view) ->setViewSuffix('php'); Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
도우미 브로커를 통해 즉시 ViewRenderer 객체를 초기화 및/또는 획득합니다.
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); $viewRenderer->setView($view) ->setViewSuffix('php');
API
대부분의 경우 간단히 ViewRenderer 개체를 생성하여 작업 도우미 브로커에 전달하기만 하면 됩니다. 인스턴스를 생성하고 등록하는 가장 쉬운 방법은 헬퍼 브로커의 getStaticHelper() 메서드를 사용하는 것입니다.
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
액션 컨트롤러가 처음으로 인스턴스화되면 ViewRenderer가 트리거되어 뷰 객체를 생성합니다. 액션 컨트롤러가 인스턴스화될 때마다 ViewRenderer의 init() 메서드를 호출하고, 액션 컨트롤러의 뷰 속성을 설정하며, 호출 시 현재 모듈에 대한 상대 경로를 사용하여 addScriptPath() 메서드를 호출합니다. 이 모듈에 대해 정의된 모든 도우미 및 필터 클래스에 유효한 클래스 접두사 매개 변수는 현재 모듈의 이름을 따서 명명됩니다. (이것은 현재 모듈의 이름을 딴 클래스 접두사를 사용하여 호출되며 모듈에 대해 정의한 모든 도우미 및 필터 클래스의 네임스페이스를 효과적으로 지정합니다.)
postDispatch() 메서드가 실행될 때마다 현재 작업에 대한 render() 메서드가 실행됩니다.
예를 들어 이 클래스는 다음과 같습니다.
// A controller class, foo module: class Foo_BarController extends Zend_Controller_Action { // Render bar/index.phtml by default; no action required public function indexAction() { } // Render bar/populate.phtml with variable 'foo' set to 'bar'. // Since view object defined at preDispatch(), it's already available. public function populateAction() { $this->view->foo = 'bar'; } } ... // in one of your view scripts: $this->foo(); // call Foo_View_Helper_Foo::foo()
ViewRenderer也定义了大量的访问器用来设定和获取视图选项。
setView($view)可以为ViewRenderer设定视图对象。以公共类属性$view获取设定值。
setNeverRender($flag = true)可以全局的启用或禁用自动解析,也就是对所有控制器都有效。如果设定为true,在所有控制器器内,postDispatch()将不会自动调用render()。getNeverRender()返回当前的设定值。
setNoRender($flag = true) 用来启用或禁用自动解析,如果设置为true,在当前控制器内,postDispatch()不会调用render()方法。这个设定在preDispatch()每次执行时会被重置。getNoRender()返回当前的设定值。
setNoController($flag = true)通知render()不要再到以控制器命名的子目录中寻找视图脚本。getNoController()返回当前值。
setNeverController($flag = true)与setNoController($flag = true)相似,但是其在全局范围内有效——也就是说,它不会在每次分发动作时重置。getNeverController()返回当前值。
setScriptAction($name)用来指定解析的视图脚本。$name是脚本的名字去掉后缀(不带控制器子目录,除非noController已开启)。如果没有指定,它将寻找以请求对象中的动作命名的视图脚本。getScriptAction()返回当前值。
setResponseSegment($name)用来指定解析到响应对象中的哪个命名片段。如果没有指定,解析到默认片断。getResponseSegment()返回当前值。
initView($path, $prefix, $options)可以指定视图的基路径,为助手和过滤器脚本设置类前缀,设定ViewRenderer选项。可以传入以下任意的标志:neverRender,noRender,noController, scriptAction,和responseSegment。
setRender($action = null, $name = null, $noController = false)可以一次设定scriptAction、responseSegment和noController。 direct()是它的别名,使得控制器中可以方便的调用。
// Render 'foo' instead of current action script $this->_helper->viewRenderer('foo'); // render form.phtml to the 'html' response segment, without using a // controller view script subdirectory: $this->_helper->viewRenderer('form', 'html', true);
Note: setRender() 和 direct()并不会实际解析视图脚本,而是提示postDispatch()和postDispatch()解析视图。
构造函数允许可选的传入参数视图对象和ViewRenderer选项,接受与initView()一样的标志(flags):
$view = new Zend_View(array('encoding' => 'UTF-8')); $options = array('noController' => true, 'neverRender' => true); $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view, $options);
뷰 개체를 추가하기 위한 뷰 기본 경로를 결정하고, 뷰 스크립트를 찾고 구문 분석하기 위한 뷰 스크립트 경로를 결정하는 데 사용되는 경로 규칙을 사용자 정의하는 몇 가지 추가 방법이 있습니다. 이러한 각 메서드에는 다음 자리 표시자(자리 표시자) 중 하나 이상이 있습니다.
:moduleDir은 현재 모듈의 기본 디렉터리(일반적으로 모듈 컨트롤러 디렉터리의 상위 디렉터리)를 나타냅니다.
:module은 현재 모듈 이름을 나타냅니다.
:controller는 현재 컨트롤러 이름을 나타냅니다.
:action은 현재 모듈 이름을 나타냅니다.
:suffix는 현재 보기 스크립트 접미사를 나타냅니다(setViewSuffix()를 통해 설정 가능).
컨트롤러 경로 규칙과 관련된 방법:
setViewBasePathSpec($spec)은 뷰 객체에 추가되는 기본 경로를 결정하는 경로 규칙을 변경할 수 있습니다. 기본 규칙은 moduleDir/views입니다. 현재 규칙은 getViewBasePathSpec()을 사용하여 언제든지 얻을 수 있습니다.
setViewScriptPathSpec($spec)을 사용하면 개별 보기 스크립트에 대한 경로를 결정하는 경로 규칙을 변경할 수 있습니다(보기 스크립트 기본 경로 제외). 기본 경로 규칙은 :controller/:action.:suffix입니다. 현재 규칙은 getViewScriptPathSpec()을 통해 언제든지 얻을 수 있습니다.
setViewScriptPathNoControllerSpec($spec)을 사용하면 noController가 적용될 때 개별 보기 스크립트에 대한 경로(보기 스크립트 기본 경로 제외)를 결정하는 경로 규칙을 변경할 수 있습니다. 기본 규칙은 action.:suffix이며 현재 규칙은 getViewScriptPathNoControllerSpec()을 통해 언제든지 얻을 수 있습니다.
경로 지정에 대한 정교한 제어를 위해 Zend_Filter_Inflector를 사용할 수 있습니다. 자세히 보면 ViewRenderer는 이미 인플렉터를 사용하여 경로 매핑을 수행합니다. 굴절기와 상호작용하려면(직접 설정하거나 기본 굴절기를 수정하는 등) 다음 방법을 사용할 수 있습니다.
getInflector()는 인플렉터를 가져옵니다. 뷰 해석기에 존재하지 않는 경우 기본 규칙을 사용하여 생성합니다.
기본적으로 정적 규칙 참조와 정적 대상을 접미사 및 모듈 디렉터리로 사용합니다. 이를 통해 다양한 뷰 확인자가 인플렉터의 기능을 동적으로 수정할 수 있습니다.
setInflector($inflector, $reference)를 사용하면 뷰 확인자와 함께 사용할 사용자 정의 inflector를 설정할 수 있습니다. $reference가 true이면 접미사 및 모듈 디렉터리를 뷰 확인자에 대한 정적 참조 및 대상 속성으로 설정합니다.
참고: 기본 검색 규칙(Conventions)
뷰 확인자는 뷰 스크립트 조회를 더 쉽게 만들기 위해 일부 경로 정규화를 수행합니다. 기본 규칙은 다음과 같습니다.
:module: 혼합된 단어와 camelCase 단어는 대시로 구분되며 전체 문자열은 소문자입니다. 예를 들어 "FooBarBaz"는 "foo-bar-baz"가 됩니다.
내부적으로, Inflector는 Zend_Filter_Word_CamelCaseToDash 및 Zend_Filter_StringToLower 필터를 사용합니다.
:controller: 혼합된 단어와 camelCase 단어는 대시로 구분됩니다. 밑줄은 디렉토리 구분 기호로 변환되며 전체 문자열은 소문자입니다. 예: "FooBar"는 "foo-bar"가 되고, "FooBar_Admin"은 "foo-bar/admin"이 됩니다.
내부적으로 inflector는 Zend_Filter_Word_CamelCaseToDash, Zend_Filter_Word_UnderscoreToSeparator 및 Zend_Filter_StringToLower 필터를 사용합니다.
:action: 혼합된 단어와 camelCase 단어는 대시로 구분됩니다. 영숫자가 아닌 문자는 대시로 변환되고 전체 문자열은 소문자로 표시됩니다. 예를 들어, "fooBar"는 "foo-bar"가 되고, "foo-barBaz"는 "foo-bar-baz"가 됩니다.
내부적으로 Inflector는 Zend_Filter_Word_CamelCaseToDash, Zend_Filter_PregReplace 및 Zend_Filter_StringToLower 필터를 사용합니다.
View Resolver API의 마지막 항목은 실제로 뷰 스크립트 경로를 결정하고 뷰를 해결하는 것입니다. 포함 내용:
renderScript($script, $name)를 사용하면 지정된 경로(선택적으로 이름이 지정된 경로 조각)에서 스크립트를 구문 분석할 수 있습니다. (renderScript($script, $name)를 사용하면 지정한 경로로 스크립트를 렌더링할 수 있으며 선택적으로 명명된 경로 세그먼트에 렌더링할 수 있습니다.) 이 방법을 사용할 때 ViewRenderer는 스크립트 이름을 자동으로 결정하지 않고 뷰 개체를 직접 참조합니다. . render()는 $script 매개변수를 전달합니다.
참고: 뷰가 응답 객체로 구문 분석되면 동일한 스크립트가 여러 번 구문 분석되는 것을 방지하도록 noRender가 설정됩니다.
참고: 기본적으로 Zend_Controller_Action::renderScript()는 ViewRenderer의 renderScript() 메서드를 프록시합니다.
getViewScript($action, $vars)는 $vars에 전달된 작업 및/또는 변수를 기반으로 보기 스크립트에 대한 경로를 생성합니다. 이 배열의 키에는 모든 경로별 키('moduleDir', 'module', 'controller', 'action' 및 'suffix')가 포함될 수 있습니다. 전달된 모든 변수가 먼저 사용되며, 그렇지 않으면 현재 요청에 따른 값이 사용됩니다.
getViewScript()는 noController 플래그의 설정 값에 따라 viewScriptPathSpec 또는 viewScriptPathNoControllerSpec을 사용합니다.
모듈, 컨트롤러, 액션의 단어 구분 기호가 대시('-')로 대체됩니다. 따라서 컨트롤러 이름 'foo.bar'와 'baz:bat' 작업은 기본 경로 규칙에 따라 뷰 스크립트 경로 'foo-bar/baz-bat.phtml'을 가져옵니다.
참고: 기본적으로 Zend_Controller_Action::getViewScript()는 ViewRenderer의 getViewScript() 메서드를 위임합니다.
render($action, $name, $noController)首先检查$name或 $noController参数是否传入,如果传入,则在ViewRenderer中设定相应的标志(分别是响应片段和noController)。然后传入$action参数到getViewScript(),最后传入计算的试图脚本路径到renderScript()。
Note: 注意使用render()的边际效应:传入的响应片段名称和noController标志在视图对象中存留。此外解析结束后noRender会被设置。
Note: 默认的,Zend_Controller_Action::render()代理 ViewRenderer的render()方法。
renderBySpec($action, $vars, $name)允许传入路径规则变量以确定创建的视图脚本路径。它把$action和$vars传入到getScriptPath(),将脚本路径结果和$name传入到renderScript()。
基础用法示例
Example #9 基本用法
大多数基础使用中,只需在bootstrap中使用助手经纪人简单的初始化和注册ViewRenderer 助手,然后在动作方法中设置变量。
// In your bootstrap: Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer'); ... // 'foo' module, 'bar' controller: class Foo_BarController extends Zend_Controller_Action { // Render bar/index.phtml by default; no action required public function indexAction() { } // Render bar/populate.phtml with variable 'foo' set to 'bar'. // Since view object defined at preDispatch(), it's already available. public function populateAction() { $this->view->foo = 'bar'; } // Renders nothing as it forwards to another action; the new action // will perform any rendering public function bazAction() { $this->_forward('index'); } // Renders nothing as it redirects to another location public function batAction() { $this->_redirect('/index'); } }
Note: 命名规则:控制器和动作名中的单词定界符
如果控制器或者动作名称由几个单词组成,分发器要求在URL中使用特定的路径和单词定界符分隔。ViewRenderer创建路径时将控制器名称中的任何路径定界符替换成实际的路径定界符('/'),任何单词定界符替换成短线('-')。对动作/foo.bar/baz.bat的调用将分发到FooBarController.php中的FooBarController::bazBatAction(),然后解析foo-bar/baz-bat.phtml;对动作/bar_baz/baz-bat的调用将分发到Bar/BazController.php中的Bar_BazController::bazBatAction(),并解析bar/baz/baz-bat.phtml。
注意到在第二个例子中,模块依然是默认的模块,但由于路径分隔符的存在,控制器的接收到的名字为Bar_BazController,该类在文件Bar/BazController.php中。ViewRenderer模拟了控制器的目录分层。
Example #10 禁用自动解析
对于某些动作和控制器,可能希望关闭自动解析——例如,如果想发送其他类型的输出(XML,JSON等),或者更简单的不想发送任何东西。有两个选项:关闭所有的自动解析(setNeverRender()),或者仅仅关闭当前动作的自动解析(setNoRender())。
// Baz controller class, bar module: class Bar_BazController extends Zend_Controller_Action { public function fooAction() { // Don't auto render this action <strong>$this->_helper->viewRenderer->setNoRender();</strong> } } // Bat controller class, bar module: class Bar_BatController extends Zend_Controller_Action { public function preDispatch() { // Never auto render this controller's actions $this->_helper->viewRenderer->setNoRender(); } }
Note: 大多数情况下,全局的关闭自动解析(setNeverRender())没有意义,因为这样ViewRenderer做的唯一件事只是自动设置了视图对象。
Example #11 选择另外的视图脚本
有些情况下需要解析另一个脚本而非以动作命名的脚本。例如,如果你有一个控制器包含增加和编辑两个动作,它们可能都显示相同的'form'视图,尽管拥有不同的值集合(value set)。只需要使用setScriptAction()或者setRender()简单的改变脚本的名称,或者以成员方法的形式调用助手,它将调用setRender()。
// Bar controller class, foo module: class Foo_BarController extends Zend_Controller_Action { public function addAction() { // Render 'bar/form.phtml' instead of 'bar/add.phtml' $this->_helper->viewRenderer('form'); } public function editAction() { // Render 'bar/form.phtml' instead of 'bar/edit.phtml' $this->_helper->viewRenderer->setScriptAction('form'); } public function processAction() { // do some validation... if (!$valid) { // Render 'bar/form.phtml' instead of 'bar/process.phtml' $this->_helper->viewRenderer->setRender('form'); return; } // otherwise continue processing... } }
Example #12 修改注册的视图Modifying the registered view
如果需要修改视图对象怎么办——例如改变助手路径或者编码?可以在控制器中修改视图对象设定,或者从ViewRenderer中抓取视图对象;两种方式引用的是同一个对象。
// Bar controller class, foo module: class Foo_BarController extends Zend_Controller_Action { public function preDispatch() { // change view encoding $this->view->setEncoding('UTF-8'); } public function bazAction() { // Get view object and set escape callback to 'htmlspecialchars' $view = $this->_helper->viewRenderer->view; $view->setEscape('htmlspecialchars'); } }
高级用法示例
Example #13 修改路径规则
有些情况下,默认的路径规则可能并不适合站点的需要。比如,希望拥有一个单独的模板树供设计人员访问(例如,如果你使用» Smarty,这是很典型的情形)。这种情况下,你可能想硬编码视图的基路径规则,为动作视图脚本路径自身创建一套规则。
假定视图的基路径(base path)为'/opt/vendor/templates',希望通过':moduleDir/:controller/:action.:suffix'引用视图脚本;如果设定了noController标志,想在顶级而不是在子目录中解析(':action.:suffix')。最终希望使用'tpl'作为视图脚本文件的后缀。
/** * In your bootstrap: */ // Different view implementation $view = new ZF_Smarty(); $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view); $viewRenderer->setViewBasePathSpec('/opt/vendor/templates') ->setViewScriptPathSpec(':module/:controller/:action.:suffix') ->setViewScriptPathNoControllerSpec(':action.:suffix') ->setViewSuffix('tpl'); Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
Example #14 一个动作中解析多个视图脚本
有时可能需要在一个动作中解析多个视图脚本。这个非常简单,多次调用render()就行了:
class SearchController extends Zend_Controller_Action { public function resultsAction() { // Assume $this->model is the current model $this->view->results = $this->model->find($this->_getParam('query', ''); // render() by default proxies to the ViewRenderer // Render first the search form and then the results $this->render('form'); $this->render('results'); } public function formAction() { // do nothing; ViewRenderer autorenders the view script } }
ViewRenderer的相关源码如下,仔细分析,并不难看出实现方法:
<?php /** * @see Zend_Controller_Action_Helper_Abstract */ require_once 'Zend/Controller/Action/Helper/Abstract.php'; /** * @see Zend_View */ require_once 'Zend/View.php'; /** * View script integration * * Zend_Controller_Action_Helper_ViewRenderer provides transparent view * integration for action controllers. It allows you to create a view object * once, and populate it throughout all actions. Several global options may be * set: * * - noController: if set true, render() will not look for view scripts in * subdirectories named after the controller * - viewSuffix: what view script filename suffix to use * * The helper autoinitializes the action controller view preDispatch(). It * determines the path to the class file, and then determines the view base * directory from there. It also uses the module name as a class prefix for * helpers and views such that if your module name is 'Search', it will set the * helper class prefix to 'Search_View_Helper' and the filter class prefix to ; * 'Search_View_Filter'. * * Usage: * <code> * // In your bootstrap: * Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_ViewRenderer()); * * // In your action controller methods: * $viewHelper = $this->_helper->getHelper('view'); * * // Don't use controller subdirectories * $viewHelper->setNoController(true); * * // Specify a different script to render: * $this->_helper->viewRenderer('form'); * * </code> * * @uses Zend_Controller_Action_Helper_Abstract * @package Zend_Controller * @subpackage Zend_Controller_Action_Helper * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com) * @license http://framework.zend.com/license/new-bsd New BSD License */ class Zend_Controller_Action_Helper_ViewRenderer extends Zend_Controller_Action_Helper_Abstract { /** * @var Zend_View_Interface */ public $view; /** * Word delimiters * @var array */ protected $_delimiters; /** * @var Zend_Filter_Inflector */ protected $_inflector; /** * Inflector target * @var string */ protected $_inflectorTarget = ''; /** * Current module directory * @var string */ protected $_moduleDir = ''; /** * Whether or not to autorender using controller name as subdirectory; * global setting (not reset at next invocation) * @var boolean */ protected $_neverController = false; /** * Whether or not to autorender postDispatch; global setting (not reset at * next invocation) * @var boolean */ protected $_neverRender = false; /** * Whether or not to use a controller name as a subdirectory when rendering * @var boolean */ protected $_noController = false; /** * Whether or not to autorender postDispatch; per controller/action setting (reset * at next invocation) * @var boolean */ protected $_noRender = false; /** * Characters representing path delimiters in the controller * @var string|array */ protected $_pathDelimiters; /** * Which named segment of the response to utilize * @var string */ protected $_responseSegment = null; /** * Which action view script to render * @var string */ protected $_scriptAction = null; /** * View object basePath * @var string */ protected $_viewBasePathSpec = ':moduleDir/views'; /** * View script path specification string * @var string */ protected $_viewScriptPathSpec = ':controller/:action.:suffix'; /** * View script path specification string, minus controller segment * @var string */ protected $_viewScriptPathNoControllerSpec = ':action.:suffix'; /** * View script suffix * @var string */ protected $_viewSuffix = 'phtml'; /** * Constructor * * Optionally set view object and options. * * @param Zend_View_Interface $view * @param array $options * @return void */ public function __construct(Zend_View_Interface $view = null, array $options = array()) { if (null !== $view) { $this->setView($view); } if (!empty($options)) { $this->_setOptions($options); } } /** * Clone - also make sure the view is cloned. * * @return void */ public function __clone() { if (isset($this->view) && $this->view instanceof Zend_View_Interface) { $this->view = clone $this->view; } } /** * Set the view object * * @param Zend_View_Interface $view * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setView(Zend_View_Interface $view) { $this->view = $view; return $this; } /** * Get current module name * * @return string */ public function getModule() { $request = $this->getRequest(); $module = $request->getModuleName(); if (null === $module) { $module = $this->getFrontController()->getDispatcher()->getDefaultModule(); } return $module; } /** * Get module directory * * @throws Zend_Controller_Action_Exception * @return string */ public function getModuleDirectory() { $module = $this->getModule(); $moduleDir = $this->getFrontController()->getControllerDirectory($module); if ((null === $moduleDir) || is_array($moduleDir)) { /** * @see Zend_Controller_Action_Exception */ require_once 'Zend/Controller/Action/Exception.php'; throw new Zend_Controller_Action_Exception('ViewRenderer cannot locate module directory for module "' . $module . '"'); } $this->_moduleDir = dirname($moduleDir); return $this->_moduleDir; } /** * Get inflector * * @return Zend_Filter_Inflector */ public function getInflector() { if (null === $this->_inflector) { /** * @see Zend_Filter_Inflector */ require_once 'Zend/Filter/Inflector.php'; /** * @see Zend_Filter_PregReplace */ require_once 'Zend/Filter/PregReplace.php'; /** * @see Zend_Filter_Word_UnderscoreToSeparator */ require_once 'Zend/Filter/Word/UnderscoreToSeparator.php'; $this->_inflector = new Zend_Filter_Inflector(); $this->_inflector->setStaticRuleReference('moduleDir', $this->_moduleDir) // moduleDir must be specified before the less specific 'module' ->addRules(array( ':module' => array('Word_CamelCaseToDash', 'StringToLower'), ':controller' => array('Word_CamelCaseToDash', new Zend_Filter_Word_UnderscoreToSeparator('/'), 'StringToLower', new Zend_Filter_PregReplace('/\./', '-')), ':action' => array('Word_CamelCaseToDash', new Zend_Filter_PregReplace('#[^a-z0-9' . preg_quote('/', '#') . ']+#i', '-'), 'StringToLower'), )) ->setStaticRuleReference('suffix', $this->_viewSuffix) ->setTargetReference($this->_inflectorTarget); } // Ensure that module directory is current $this->getModuleDirectory(); return $this->_inflector; } /** * Set inflector * * @param Zend_Filter_Inflector $inflector * @param boolean $reference Whether the moduleDir, target, and suffix should be set as references to ViewRenderer properties * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setInflector(Zend_Filter_Inflector $inflector, $reference = false) { $this->_inflector = $inflector; if ($reference) { $this->_inflector->setStaticRuleReference('suffix', $this->_viewSuffix) ->setStaticRuleReference('moduleDir', $this->_moduleDir) ->setTargetReference($this->_inflectorTarget); } return $this; } /** * Set inflector target * * @param string $target * @return void */ protected function _setInflectorTarget($target) { $this->_inflectorTarget = (string) $target; } /** * Set internal module directory representation * * @param string $dir * @return void */ protected function _setModuleDir($dir) { $this->_moduleDir = (string) $dir; } /** * Get internal module directory representation * * @return string */ protected function _getModuleDir() { return $this->_moduleDir; } /** * Generate a class prefix for helper and filter classes * * @return string */ protected function _generateDefaultPrefix() { $default = 'Zend_View'; if (null === $this->_actionController) { return $default; } $class = get_class($this->_actionController); if (!strstr($class, '_')) { return $default; } $module = $this->getModule(); if ('default' == $module) { return $default; } $prefix = substr($class, 0, strpos($class, '_')) . '_View'; return $prefix; } /** * Retrieve base path based on location of current action controller * * @return string */ protected function _getBasePath() { if (null === $this->_actionController) { return './views'; } $inflector = $this->getInflector(); $this->_setInflectorTarget($this->getViewBasePathSpec()); $dispatcher = $this->getFrontController()->getDispatcher(); $request = $this->getRequest(); $parts = array( 'module' => (($moduleName = $request->getModuleName()) != '') ? $dispatcher->formatModuleName($moduleName) : $moduleName, 'controller' => $request->getControllerName(), 'action' => $dispatcher->formatActionName($request->getActionName()) ); $path = $inflector->filter($parts); return $path; } /** * Set options * * @param array $options * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ protected function _setOptions(array $options) { foreach ($options as $key => $value) { switch ($key) { case 'neverRender': case 'neverController': case 'noController': case 'noRender': $property = '_' . $key; $this->{$property} = ($value) ? true : false; break; case 'responseSegment': case 'scriptAction': case 'viewBasePathSpec': case 'viewScriptPathSpec': case 'viewScriptPathNoControllerSpec': case 'viewSuffix': $property = '_' . $key; $this->{$property} = (string) $value; break; default: break; } } return $this; } /** * Initialize the view object * * $options may contain the following keys: * - neverRender - flag dis/enabling postDispatch() autorender (affects all subsequent calls) * - noController - flag indicating whether or not to look for view scripts in subdirectories named after the controller * - noRender - flag indicating whether or not to autorender postDispatch() * - responseSegment - which named response segment to render a view script to * - scriptAction - what action script to render * - viewBasePathSpec - specification to use for determining view base path * - viewScriptPathSpec - specification to use for determining view script paths * - viewScriptPathNoControllerSpec - specification to use for determining view script paths when noController flag is set * - viewSuffix - what view script filename suffix to use * * @param string $path * @param string $prefix * @param array $options * @throws Zend_Controller_Action_Exception * @return void */ public function initView($path = null, $prefix = null, array $options = array()) { if (null === $this->view) { $this->setView(new Zend_View()); } // Reset some flags every time $options['noController'] = (isset($options['noController'])) ? $options['noController'] : false; $options['noRender'] = (isset($options['noRender'])) ? $options['noRender'] : false; $this->_scriptAction = null; $this->_responseSegment = null; // Set options first; may be used to determine other initializations $this->_setOptions($options); // Get base view path if (empty($path)) { $path = $this->_getBasePath(); if (empty($path)) { /** * @see Zend_Controller_Action_Exception */ require_once 'Zend/Controller/Action/Exception.php'; throw new Zend_Controller_Action_Exception('ViewRenderer initialization failed: retrieved view base path is empty'); } } if (null === $prefix) { $prefix = $this->_generateDefaultPrefix(); } // Determine if this path has already been registered $currentPaths = $this->view->getScriptPaths(); $path = str_replace(array('/', '\\'), '/', $path); $pathExists = false; foreach ($currentPaths as $tmpPath) { $tmpPath = str_replace(array('/', '\\'), '/', $tmpPath); if (strstr($tmpPath, $path)) { $pathExists = true; break; } } if (!$pathExists) { $this->view->addBasePath($path, $prefix); } // Register view with action controller (unless already registered) if ((null !== $this->_actionController) && (null === $this->_actionController->view)) { $this->_actionController->view = $this->view; $this->_actionController->viewSuffix = $this->_viewSuffix; } } /** * init - initialize view * * @return void */ public function init() { if ($this->getFrontController()->getParam('noViewRenderer')) { return; } $this->initView(); } /** * Set view basePath specification * * Specification can contain one or more of the following: * - :moduleDir - current module directory * - :controller - name of current controller in the request * - :action - name of current action in the request * - :module - name of current module in the request * * @param string $path * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setViewBasePathSpec($path) { $this->_viewBasePathSpec = (string) $path; return $this; } /** * Retrieve the current view basePath specification string * * @return string */ public function getViewBasePathSpec() { return $this->_viewBasePathSpec; } /** * Set view script path specification * * Specification can contain one or more of the following: * - :moduleDir - current module directory * - :controller - name of current controller in the request * - :action - name of current action in the request * - :module - name of current module in the request * * @param string $path * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setViewScriptPathSpec($path) { $this->_viewScriptPathSpec = (string) $path; return $this; } /** * Retrieve the current view script path specification string * * @return string */ public function getViewScriptPathSpec() { return $this->_viewScriptPathSpec; } /** * Set view script path specification (no controller variant) * * Specification can contain one or more of the following: * - :moduleDir - current module directory * - :controller - name of current controller in the request * - :action - name of current action in the request * - :module - name of current module in the request * * :controller will likely be ignored in this variant. * * @param string $path * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setViewScriptPathNoControllerSpec($path) { $this->_viewScriptPathNoControllerSpec = (string) $path; return $this; } /** * Retrieve the current view script path specification string (no controller variant) * * @return string */ public function getViewScriptPathNoControllerSpec() { return $this->_viewScriptPathNoControllerSpec; } /** * Get a view script based on an action and/or other variables * * Uses values found in current request if no values passed in $vars. * * If {@link $_noController} is set, uses {@link $_viewScriptPathNoControllerSpec}; * otherwise, uses {@link $_viewScriptPathSpec}. * * @param string $action * @param array $vars * @return string */ public function getViewScript($action = null, array $vars = array()) { $request = $this->getRequest(); if ((null === $action) && (!isset($vars['action']))) { $action = $this->getScriptAction(); if (null === $action) { $action = $request->getActionName(); } $vars['action'] = $action; } elseif (null !== $action) { $vars['action'] = $action; } $replacePattern = array('/[^a-z0-9]+$/i', '/^[^a-z0-9]+/i'); $vars['action'] = preg_replace($replacePattern, '', $vars['action']); $inflector = $this->getInflector(); if ($this->getNoController() || $this->getNeverController()) { $this->_setInflectorTarget($this->getViewScriptPathNoControllerSpec()); } else { $this->_setInflectorTarget($this->getViewScriptPathSpec()); } return $this->_translateSpec($vars); } /** * Set the neverRender flag (i.e., globally dis/enable autorendering) * * @param boolean $flag * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setNeverRender($flag = true) { $this->_neverRender = ($flag) ? true : false; return $this; } /** * Retrieve neverRender flag value * * @return boolean */ public function getNeverRender() { return $this->_neverRender; } /** * Set the noRender flag (i.e., whether or not to autorender) * * @param boolean $flag * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setNoRender($flag = true) { $this->_noRender = ($flag) ? true : false; return $this; } /** * Retrieve noRender flag value * * @return boolean */ public function getNoRender() { return $this->_noRender; } /** * Set the view script to use * * @param string $name * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setScriptAction($name) { $this->_scriptAction = (string) $name; return $this; } /** * Retrieve view script name * * @return string */ public function getScriptAction() { return $this->_scriptAction; } /** * Set the response segment name * * @param string $name * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setResponseSegment($name) { if (null === $name) { $this->_responseSegment = null; } else { $this->_responseSegment = (string) $name; } return $this; } /** * Retrieve named response segment name * * @return string */ public function getResponseSegment() { return $this->_responseSegment; } /** * Set the noController flag (i.e., whether or not to render into controller subdirectories) * * @param boolean $flag * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setNoController($flag = true) { $this->_noController = ($flag) ? true : false; return $this; } /** * Retrieve noController flag value * * @return boolean */ public function getNoController() { return $this->_noController; } /** * Set the neverController flag (i.e., whether or not to render into controller subdirectories) * * @param boolean $flag * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setNeverController($flag = true) { $this->_neverController = ($flag) ? true : false; return $this; } /** * Retrieve neverController flag value * * @return boolean */ public function getNeverController() { return $this->_neverController; } /** * Set view script suffix * * @param string $suffix * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setViewSuffix($suffix) { $this->_viewSuffix = (string) $suffix; return $this; } /** * Get view script suffix * * @return string */ public function getViewSuffix() { return $this->_viewSuffix; } /** * Set options for rendering a view script * * @param string $action View script to render * @param string $name Response named segment to render to * @param boolean $noController Whether or not to render within a subdirectory named after the controller * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface */ public function setRender($action = null, $name = null, $noController = null) { if (null !== $action) { $this->setScriptAction($action); } if (null !== $name) { $this->setResponseSegment($name); } if (null !== $noController) { $this->setNoController($noController); } return $this; } /** * Inflect based on provided vars * * Allowed variables are: * - :moduleDir - current module directory * - :module - current module name * - :controller - current controller name * - :action - current action name * - :suffix - view script file suffix * * @param array $vars * @return string */ protected function _translateSpec(array $vars = array()) { $inflector = $this->getInflector(); $request = $this->getRequest(); $dispatcher = $this->getFrontController()->getDispatcher(); $module = $dispatcher->formatModuleName($request->getModuleName()); $controller = $request->getControllerName(); $action = $dispatcher->formatActionName($request->getActionName()); $params = compact('module', 'controller', 'action'); foreach ($vars as $key => $value) { switch ($key) { case 'module': case 'controller': case 'action': case 'moduleDir': case 'suffix': $params[$key] = (string) $value; break; default: break; } } if (isset($params['suffix'])) { $origSuffix = $this->getViewSuffix(); $this->setViewSuffix($params['suffix']); } if (isset($params['moduleDir'])) { $origModuleDir = $this->_getModuleDir(); $this->_setModuleDir($params['moduleDir']); } $filtered = $inflector->filter($params); if (isset($params['suffix'])) { $this->setViewSuffix($origSuffix); } if (isset($params['moduleDir'])) { $this->_setModuleDir($origModuleDir); } return $filtered; } /** * Render a view script (optionally to a named response segment) * * Sets the noRender flag to true when called. * * @param string $script * @param string $name * @return void */ public function renderScript($script, $name = null) { if (null === $name) { $name = $this->getResponseSegment(); } $this->getResponse()->appendBody( $this->view->render($script), $name ); $this->setNoRender(); } /** * Render a view based on path specifications * * Renders a view based on the view script path specifications. * * @param string $action * @param string $name * @param boolean $noController * @return void */ public function render($action = null, $name = null, $noController = null) { $this->setRender($action, $name, $noController); $path = $this->getViewScript(); $this->renderScript($path, $name); } /** * Render a script based on specification variables * * Pass an action, and one or more specification variables (view script suffix) * to determine the view script path, and render that script. * * @param string $action * @param array $vars * @param string $name * @return void */ public function renderBySpec($action = null, array $vars = array(), $name = null) { if (null !== $name) { $this->setResponseSegment($name); } $path = $this->getViewScript($action, $vars); $this->renderScript($path); } /** * postDispatch - auto render a view * * Only autorenders if: * - _noRender is false * - action controller is present * - request has not been re-dispatched (i.e., _forward() has not been called) * - response is not a redirect * * @return void */ public function postDispatch() { if ($this->_shouldRender()) { $this->render(); } } /** * Should the ViewRenderer render a view script? * * @return boolean */ protected function _shouldRender() { return (!$this->getFrontController()->getParam('noViewRenderer') && !$this->_neverRender && !$this->_noRender && (null !== $this->_actionController) && $this->getRequest()->isDispatched() && !$this->getResponse()->isRedirect() ); } /** * Use this helper as a method; proxies to setRender() * * @param string $action * @param string $name * @param boolean $noController * @return void */ public function direct($action = null, $name = null, $noController = null) { $this->setRender($action, $name, $noController); } }
更多关于zend相关内容感兴趣的读者可查看本站专题:《Zend FrameWork框架入门教程》、《php优秀开发框架总结》、《Yii框架入门及常用技巧总结》、《ThinkPHP入门教程》、《php面向对象程序设计入门教程》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》
希望本文所述对大家基于Zend Framework框架的PHP程序设计有所帮助。