主题可以使你快捷地切换页面的外观。
要使用主题,只需在控制器中指定主题名称:
1 class ExampleController extends AppController { 2 public $theme = 'Example'; 3 }
在 2.1 版更改: 2.1 以前的版本需要使用 $this->viewClass = 'Theme' 设置主题。 2.1 删除了这一要求,并在正常的 View 类中支持主题。
也可以在动作或者 beforeFilter、beforeRender 回调中设置或改变主题:
1 $this->theme = 'AnotherExample';
主题视图文件要放在 /app/View/Themed/ 文件夹。在主题文件夹中,使用与主题相同的名字建立文件夹。例如,上面的主题存放在 /app/View/Themed/AnotherExample。 重要的是要记住 CakePHP 期望主题名遵循驼峰命名法。此外,/app/View/Themed/Example/ 文件夹的结构就与 /app/View/ 文件夹相同。
例如,Posts 控制器的 edit 动作所渲染的视图文件是 /app/View/Themed/Example/Posts/edit.ctp。布局文件则存放在 /app/View/Themed/Example/Layouts/。
如果主题中没有某个视图文件,CakePHP 就尝试在 /app/View/ 文件夹中寻找它。如此一来,你只需要在主题文件夹中根据实际情况建立主要的视图来简单的覆盖需要覆盖的视图文件。
主题能够包含静态部件和视图文件。 一个主题可以在它的 web 根目录包含所需的部件。这样就更易于打包和发布主题。在开发中,主题部件的请求将被 Dispatcher 处理。为了在生产环境中提高运行效率,推荐符号链接或复制主题部件到应用程序的 web 根目录。更多信息参见后文。
在主题中建立类似 app/View/Themed/
CakePHP 内置的所有助手都支持主题并自动建立正确的路径。 像视图文件一样,如果主题文件夹中不存在某些助手需要的文件,将到主根目录中寻找它们:
1 // 在名为 'purple_cupcake' 的主题中 2 $this->Html->css('main.css'); 3 4 // 建立如下的文件 5 /theme/purple_cupcake/css/main.css 6 7 // 并链接到 8 app/View/Themed/PurpleCupcake/webroot/css/main.css
提高插件和主题部件的运行效率
一个众所周知的事实是,通过 PHP 调用处理部件要比不通过 PHP 调用慢。在需要更高的运行效率的场合,核心团队已经采取了一些措施让插件和主题部件尽可能地快速运行。此时,推荐你建立符号链接或者复制 插件/主题部件到app/webroot ,并通过 CakePHP 匹配这些路径。
2.3 版后已移除: 被 传输文件 取代。
媒体视图允许你向用户传送二进制文件。例如,你可能希望有一个位于 web 根目录之外的禁止用户直接链接的文件目录。你可以使用媒体视图从 /app/ 下的一个特定文件夹中提取文件,允许你在将文件交给用户前执行权限验证。
要使用媒体视图,你只需告诉控制器用媒体视图类取代默认的视图类。然后在附加参数中传递媒体视图文件的位置:
1 class ExampleController extends AppController { 2 public function download() { 3 $this->viewClass = 'Media'; 4 // Download app/outside_webroot_dir/example.zip 5 $params = array( 6 'id' => 'example.zip', 7 'name' => 'example', 8 'download' => true, 9 'extension' => 'zip', 10 'path' => APP . 'outside_webroot_dir' . DS 11 ); 12 $this->set($params); 13 } 14 }
下面是一个渲染视图 $mimeType 数组中不存在的媒体类型的文件的例子。我们也可以使用相对于 app/webroot 文件夹的相对路径:
1 public function download() { 2 $this->viewClass = 'Media'; 3 // Render app/webroot/files/example.docx 4 $params = array( 5 'id' => 'example.docx', 6 'name' => 'example', 7 'extension' => 'docx', 8 'mimeType' => array( 9 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' 10 ), 11 'path' => 'files' . DS 12 ); 13 $this->set($params); 14 }
可设置的参数
CakePHP 2.1 是有两个新的视图类。XmlView 和 JsonView 让我们更易于建立 XML 和 JSON 响应,并与RequestHandlerComponent 整合。
通过在应用程序中允许 RequestHandlerComponent ,和允许支持 xml 和/或 json 扩展,你可以自动利用新的视图类。XmlView 和 JsonView 此页的剩余部分以数据视图来引用。
有两种生成数据视图的方法。一种是通过使用 _serialize 键,一种是通过建立正常的视图文件。
在使用数据视图类之前,需要做些设置:
2.3 新版功能: 增加了 RequestHandlerComponent::viewClassMap() 方法用于映射类型到视图类。 viewClassMap 选项在之前的版本中也不工作。
在向路由文件添加 Router::parseExtensions('json'); 后,CakePHP 将在收到以 .json 结束的或者带有application/json 头信息的请求时自动切换视图类。
_serialize 键是一个特殊的视图变量 - 表明在使用数据视图时其它的视图变量将被序列化。 如果在数据转换成 json/xml 之前,你不需要做自定义格式化,这种方式就可以让你跳过为控制器动作定义视图文件这一步。
如果在生成响应之前需要格式化或操纵视图变量,你就需要使用视图文件。_serialize 的值可以是准备序列化的一个字符串或者一个视图变量数组:
1 class PostsController extends AppController { 2 public function index() { 3 $this->set('posts', $this->paginate()); 4 $this->set('_serialize', array('posts')); 5 } 6 }
你也可以将 _serialize 定义为一个用于绑定的视图变量数组:
1 class PostsController extends AppController { 2 public function index() { 3 // some code that created $posts and $comments 4 $this->set(compact('posts', 'comments')); 5 $this->set('_serialize', array('posts', 'comments')); 6 } 7 }
当使用 XmlView 时,以数组方式定义 _serialize 有一个附加的好处,自动添加一个顶级的
如果在建立最终的输出前需要做一些视图内容的操作,你可能需要使用视图文件。例如,如果我们有 posts,其中一个域包含生成 HTML,我们可能想要忽略 JSON 输出。这时,视图文件就派上了用场:
1 // 控制器代码 2 class PostsController extends AppController { 3 public function index() { 4 $this->set(compact('posts', 'comments')); 5 } 6 } 7 8 // 视图代码 - app/View/Posts/json/index.ctp 9 foreach ($posts as &$post) { 10 unset($post['Post']['generated_html']); 11 } 12 echo json_encode(compact('posts', 'comments'));
你能做更多更多地复杂操作,也可以使用助手进行格式化。
注解
数据视图类不支持布局。它们假定视图文件将输出序列化内容。
一个生成 Xml 视图数据的视图类。见上文如何在应用程序中使用 XmlView。
当使用 _serialize 时,XmlView 默认将使用一个
2.3 新版功能: 增加了 _rootNode 特性。
class JsonView一个生成 Json 视图数据的视图类。风上文如何在应用程序中使用 JsonView。
助手是应用程序显示层中类似组件的类。它们包含在多个视图、元素或布局间共享的显示逻辑。这一章将向你展示如何建立你自己的助手,并且描述了 CakePHP 的核心助手能帮助你实现的基本任务。
CakePHP 包含了一些帮助建立视图的助手。 它们协助建立格式良好的标签(包括表单),帮助格式化文本、时间和数字,甚至还能为 Ajax 功能提速。关于 CakePHP 中的助手的更多信息,请浏览 助手 。
在 CakePHP 中,你可以通过让控制器知道助手的存在来使助手可用。 每个控制器有一个 $helpers 属性,列出了可以在视图中使用的助手。要使一个助手在视图中可用,将这个助手的名字添加到控制器的 $helpers 数组:
1 class BakeriesController extends AppController { 2 public $helpers = array('Form', 'Html', 'Js', 'Time'); 3 }
在 CakePHP 的其它位置,添加插件内的助手请使用 插件语法:
1 class BakeriesController extends AppController { 2 public $helpers = array('Blog.Comment'); 3 }
你还可以在动作内添加助手,这样它们就只在这个动作中可用,但在同一控制器的其它动作中无法使用。这会节省那些不需要助手的动作的计算能力,同时保持控制器的良好组织:
1 class BakeriesController extends AppController { 2 public function bake { 3 $this->helpers[] = 'Time'; 4 } 5 public function mix { 6 // Time 助手不加载,也不能使用 7 } 8 }
如果需要在所有的控制器中使用一个助手,将其加入到 /app/Controller/AppController.php 文件的 $helpers 数组中(如果它不存在,就创建一个)。记住,包含默认的 Html 和 Form 助手:
1 class AppController extends Controller { 2 public $helpers = array('Form', 'Html', 'Js', 'Time'); 3 }
你可以传递选项给助手。这些选项能够被用于设置属性值或者修改助手的行为:
1 class AwesomeHelper extends AppHelper { 2 public function __construct(View $view, $settings = array()) { 3 parent::__construct($view, $settings); 4 debug($settings); 5 } 6 }
1 class AwesomeController extends AppController { 2 public $helpers = array('Awesome' => array('option1' => 'value1')); 3 }
2.3 版的选项合并了助手的 Helper::$settings 属性。
一个公用的设置是 className 选项,它允许你在视图中建立助手别名。这个特性在你想要替换 $this-Html 或者引用自定义实现的其它公用助手时很有用:
1 // app/Controller/PostsController.php 2 class PostsController extends AppController { 3 public $helpers = array( 4 'Html' => array( 5 'className' => 'MyHtml' 6 ) 7 ); 8 }
1 // app/View/Helper/MyHtmlHelper.php 2 App::uses('HtmlHelper', 'View/Helper'); 3 class MyHtmlHelper extends HtmlHelper { 4 // Add your code to override the core HtmlHelper 5 }
上面的代码将视图中的 MyHtmlHelper 的别名设置为 $this->Html 。
注解
为助手定义别名将在所有使用别名的位置替换其实例,包括在其它助手中。
小技巧
在使用核心的 PagesController 时,为 Html 或者 Session 助手定义别名将无法工作。 最好是将lib/Cake/Controller/PagesController.php 复制到 app/Controller/ 文件夹。
使用助手设置允许你声明配置助手,并在控制器动作之外维护配置逻辑。如果你有不能包含在类声明中的配置选项,你可以在控制器的 beforeRender 回调中设置它们:
1 class PostsController extends AppController { 2 public function beforeRender() { 3 parent::beforeRender(); 4 $this->helpers['CustomStuff'] = $this->_getCustomStuffSettings(); 5 } 6 }
一旦你已经在控制器中配置了你想使用的助手,它就成为视图中的公用属性,如果你使用 HtmlHelper ,你就可以通过如下方式访问它:
1 echo $this->Html->css('styles');
上面的代码调用了 HtmlHelper 的 css 方法。人可以使用 $this->{$helperName} 访问任何已加载的助手。有时你可能需要从视图中动态加载一个助手。你可以使用视图的 HelperCollection 来做到这一点:
1 $mediaHelper = $this->Helpers->load('Media', $mediaSettings);
HelperCollection 是一个 集合 ,并且支持在 CakePHP 的任意一处使用集合 API。
如果内核助手(或者展示在 github 和 Bakery中的)不能满足要求,可以很容易的创建助手。
假设我们想要创建一个能够用于输出一个特别制定的在应用程序的许多位置需要的 CSS 风格的链接的助手。为了适合你的逻辑及 CakePHP 现有助手结构,你需要在 /app/View/Helper 中创建一个新的类。调用我们的 LinkHelper 助手。这个真实的 PHP 类文件类似于:
1 /* /app/View/Helper/LinkHelper.php */ 2 App::uses('AppHelper', 'View/Helper'); 3 4 class LinkHelper extends AppHelper { 5 public function makeEdit($title, $url) { 6 // 建立特别格式的链接的逻辑放在这... 7 } 8 }
注解
助手必须继承 AppHelper 或者 Helper,也可以使用 助手 API 实现全部回调。
你也许会希望使用其它助手中已经存在的功能。要做到这一点,你可以指定助手使用 $helpers 数组,格式与控制器中的格式类似:
1 /* /app/View/Helper/LinkHelper.php (using other helpers) */ 2 App::uses('AppHelper', 'View/Helper'); 3 4 class LinkHelper extends AppHelper { 5 public $helpers = array('Html'); 6 7 public function makeEdit($title, $url) { 8 // 使用 HTML 助手输出 9 // 格式化的数据: 10 11 $link = $this->Html->link($title, $url, array('class' => 'edit')); 12 13 return '' . $link . ''; 14 } 15 }
使用助手
一旦创建了助手,并放进了 /app/View/Helper/,你也可以在控制器中使用特别变量 $helpers :
1 class PostsController extends AppController { 2 public $helpers = array('Link'); 3 }
只要控制器知道这个新类的存在,你就可以在视图中使用它(通过访问以这个助手命名的对象):
1 2 echo $this->Link->makeEdit('Change this Recipe', '/recipes/edit/5'); ?>
为所有助手创建功能
所有的助手都继承自一个特殊类 AppHelper(类似于所有的模型都继承 AppModel 和所有的控制器都继承 AppController)。要为所有的助手创建功能,建立 /app/View/Helper/AppHelper.php 这个文件:
1 App::uses('Helper', 'View'); 2 3 class AppHelper extends Helper { 4 public function customMethod() { 5 } 6 }
助手 API
助手的基类。它提供了一些工具方法,和加载其它助手的功能。
Helper::webroot($file)解析一个文件名到应用程序的 web 根目录。如果一个主题激活并且此文件在当前主题的 web 根目录中存在,到这个主题文件的路径将被返回。
Helper::url($url, $full = false)创建一个 HTML 转义 URL,委托给 Router::url() 方法。
Helper::value($optiOns= array(), $field = null, $key = 'value')得到给定的输入名的值。
Helper::domId($optiOns= null, $id = 'id')为当前选择的域生成一个驼峰命名的 id 值。 在 AppHelper 中覆盖这个方法允许你改变 CakePHP 生成 ID 属性的方式。
在所有的视图文件被渲染前调用。 包括元素、视图、父视图和布局。
Helper::afterRenderFile($viewFile, $content)在所有的视图文件被渲染后调用。包括元素、视图、父视图和布局。 这个回调可以编辑并返回 $content 以改变将在浏览器中显示的内容的渲染方式。
Helper::beforeRender($viewFile)beforeRender 方法在控制器的 beforeRender 调用之后,但控制器实际渲染视图和布局之前调用。 接收被渲染的文件作为其参数。
Helper::afterRender($viewFile)在视图被渲染之后但布局被渲染之前调用。
Helper::beforeLayout($layoutFile)在布局被渲染之前调用。接受布局文件名作为其参数。
Helper::afterLayout($layoutFile)在布局渲染完成之后调用。接受布局文件名作为其参数。