看法
View是MVC中的V。 视图负责生成请求所请求的特定输出。 通常,这是通过 HTML、XML 或 JSON 完成的,但提供文件流并创建 PDF 供用户下载也是视口的责任。
CakePHP 附带了一些外部视图类,可以处理最常见的渲染情况:
查看模板
CakePHP 的视图层是您与用户通信的方式。 在大多数情况下,视图将向浏览器显示 (X)HTML 文档,但您可能还需要向 Flash 对象提供 AMF 数据、通过 SOAP 回复远程应用程序或向用户输出 CSV 文件。
默认情况下,CakePHP的视图文件是普通的PHP文件,默认扩展名是.ctp(CakePHP Template)。 这些文件包括所有表示层逻辑,这些逻辑将从控制器获取的数据转换为您所服务的受众所需的格式。 如果您更喜欢使用 Twig 或 Smarty 等模板语言,视图泛型可以将您的模板语言与 CakePHP 联系起来。
视图文件存放在/app/View/目录下,该目录以使用该视图文件的控制器命名,并以对应的action为文件名。 例如,产品控制器的“view()”操作的视图文件通常应位于/app/View/Products/view.ctp。
CakePHP 的视图层可以由许多不同的部分组成。 每个部分都有不同的用途,本章也将介绍:
扩展视图
2.1 新功能。
视图扩展允许您将一个视图包含在另一个视图中。 与此相结合,它提供了一种强大的方式来维护您的视图。 例如,您的应用程序有一个侧边栏,该侧边栏会根据呈现的特定视图而变化。 通过扩展共享视图文件,您可以避免重复侧边栏的共享标记,而只定义不同的部分:
// app/View/Common/view.ctp <?php echo $this->fetch('title'); ?> <?php echo $this->fetch('content'); ?>Related actions
<?php echo $this->fetch('sidebar'); ?>
上面的视图文件可以用作父视图。 它需要扩展其视图来定义侧边栏和标题栏。 内容块是由 CakePHP 创建的特殊块。 它将包括子视图中任何未捕获的内容。 假设我们的视图文件有一个 $posts 变量,其中包含与我们的帖子相关的数据。 我们的视图可能如下所示:
<?php // app/View/Posts/view.ctp $this->extend('/Common/view'); $this->assign('title', $post); $this->start('sidebar'); ?> <?php echo $this->Html->link('edit', array( 'action' => 'edit', $post['Post']['id'] )); ?> <?php $this->end(); ?> // 其余的内容会作为父视图中的 'content' 代码块。 <?php echo h($post['Post']['body']);
上面帖子中的视图展示了如何扩展视图并填充一组代码块。 任何不在定义的代码块内的内容都会被捕获并加载到称为内容的特殊代码块中。 当视图包含对extend()的调用时,程序将继续执行,直到当前视图文件末尾。 执行完成后,将呈现扩展视图。 在视图文件中多次调用extend()将更改接下来要处理的父视图:
$this->extend('/Common/view'); $this->extend('/Common/index');
上面的代码将导致 /Common/index.ctp 被渲染为当前视图的父视图。
如有必要,您可以根据需要嵌套任意多个级别的增强视图。 如有必要,每个视图都可以补充另一个视图。 每个父视图都将前一个视图的内容作为内容块获取。
评论
您应该避免使用内容作为应用程序中代码块的名称。 CakePHP 使用它来增加视图中未捕获的内容。
使用视图块
2.1 新功能。
视图代码块取代 $scripts_for_layout 并提供灵活的 API,允许您引用视图/布局中其他位置定义的代码片段或代码块。 例如,代码块非常适合实现侧边栏或位于布局顶部的区域/在顶部加载内容。 代码块可以通过两种方式定义,要么作为捕获块,要么直接作为形式参数。 start()、append() 和 end() 方法可用于捕获代码块:
// 创建侧边栏代码块。 $this->start('sidebar'); echo $this->element('sidebar/recent_topics'); echo $this->element('sidebar/recent_comments'); $this->end(); // 之后添加内容到侧边栏的末尾。 $this->append('sidebar'); echo $this->element('sidebar/popular_topics'); $this->end();
您还可以使用 start() 多次向代码块添加内容。 allocate() 方法可用于随时消除或覆盖代码块:
// 清除侧边栏代码块之前的内容。 $this->assign('sidebar', '');
在 2.3 版本中,添加了一些使用代码块的新方法。 prepend() 方法用于在现有代码块的开头插入内容:
// 在侧边栏的开头插入内容 $this->prepend('sidebar', 'this content goes on top of sidebar');
仅当代码块为空或未定义时,startIfEmpty() 方法才可用于启动代码块。 如果代码块已经存在,则当前捕获的内容将被丢弃。 当您想要有条件地定义仍然定义了过时的默认内容的代码块时,这非常有用:
// 在一个视图文件中。 // 创建一个导航栏代码块 $this->startIfEmpty('navbar'); echo $this->element('navbar'); echo $this->element('notifications'); $this->end();
// 在一个父视图/布局中 <?php $this->startIfEmpty('navbar'); ?>If the block is not defined by now - show this instead
<?php $this->end(); ?> // 在一个父视图/布局中更靠后的地方 echo $this->fetch('navbar');
在前面的反例中,导航栏块只会包含第一部分中添加的内容。由于代码块是在子视图中定义的,因此它包含
标签的默认内容将被丢弃。
2.3 版本中的新功能:startIfEmpty() 和 prepend() 在 2.3 版本中已弃用。
评论
您应该避免使用内容作为代码块的名称。 CakePHP 在内部使用它来增强视图和查看布局中的内容。
显示代码块
2.1 新功能。
您可以使用 fetch() 方法显示代码块。 fetch() 方法将安全地输出一个代码块,如果代码块不存在则返回 '':
echo $this->fetch('sidebar');
您还可以使用 fetch() 仅显示代码块周围的内容(如果该代码块存在)。 当您想要在布局或增强视图中有条件地显示标题或其他内容时,这非常有用:
// 在 app/View/Layouts/default.ctp 中 <?php if ($this->fetch('menu')): ?> <?php endif; ?>
在2.3.0版本中,当代码块没有内容时,您可以为它提供默认值。 这使您可以轻松地为空状态添加占位符内容。 您可以使用第二个参数提供默认值:
你的购物车
<?php echo $this->fetch('cart', '你的购物车为空'); ?>
2.3版本修改:2.3版本增加$default参数。
代码块用于脚本和 CSS 文件中
2.1 新功能。
代码块替换了过时的 $scripts_for_layout 布局变量。 您应该使用代码块。 与视图块、its 和 方法紧密集成,当与 inline = false 选项一起使用时,用各自的名称更新块:
<?php // 在你的视图文件中 $this->Html->script('carousel', array('inline' => false)); $this->Html->css('carousel', array('inline' => false)); ?> // 在你的布局文件中。<?php echo $this->fetch('title'); ?> <?php echo $this->fetch('script'); ?> <?php echo $this->fetch('css'); ?> // 后面是布局的其余部分
它还可以让您控制哪些脚本和 CSS 出现在哪些代码块中:
// 在你的视图中 $this->Html->script('carousel', array('block' => 'scriptBottom')); // 在你的布局中 echo $this->fetch('scriptBottom');
布局
布局中有丰富的包装视图的表示代码。 您想要在所有视图中出现的任何内容都应该放置在布局中。
CakePHP 的默认布局位于 /app/View/Layouts/default.ctp。 如果您想更改应用程序的整体外观,那么这是正确的起点,因为当页面呈现时,控制器呈现的视图代码将放置在默认布局的顶部。
其他布局文件应放置在 /app/View/Layouts 目录中。 当你创建布局时,你需要告诉 CakePHP 视图的输出应该去哪里。 为此,请确保您的布局在某处包含 $this->fetch('content') 。 默认布局的示例可能如下所示:
<?php echo $this->fetch('title'); ?> <?php echo $this->fetch('meta'); echo $this->fetch('css'); echo $this->fetch('script'); ?> <?php echo $this->fetch('content'); ?>
评论
在2.1版本之前,没有fetch()方法。 fetch('content') 取代了 $content_for_layout,并且 fetch('meta')、fetch('css') 和 fetch('script') (生成的行)包含在 2.0 版本中的 $scripts_for_layout 变量中。
脚本、CSS 和元块包含使用外部 HTML 帮助程序在视图中定义的任何内容。 这可用于从视图引入 javascript 和 CSS 文件。
评论
在视图文件中使用 and 时,为“inline”选项指定“false”,以将 html 源代码加载到同名的代码块中。 (有关使用的更多详细信息,请参阅 API。)
内容代码块包含渲染视图的内容。
$title_for_layout 包含页面的标题。 该变量是手动生成的,但您可以通过在控制器/视图中为其提供形式参数来覆盖它。
评论
$title_for_layout 在 2.5 版本中已过时。 请在布局中使用 $this->fetch('title') 和 $this->assign('title', 'page title') 。
设置布局标题的最简单方法是在控制器中设置 $title_for_layout 变量:
class UsersController extends AppController { public function view_active() { $this->set('title_for_layout', 'View Active Users'); } }
您还可以在视图文件中设置 title_for_layout 变量:
$this->set('title_for_layout', $titleContent);
您可以根据需要创建任意数量的布局:只需将它们放在 app/View/Layouts 目录中,并使用控制器或视图属性在控制器操作中切换布局:
// 从一个控制器 public function admin_view() { // 代码 $this->layout = 'admin'; } // 从一个视图文件 $this->layout = 'loggedin';
例如,如果我网站的一个区域包含广告横幅,我可能会使用广告横幅创建一个新布局,并将其指定为所有控制器操作的布局,如下所示:
class UsersController extends AppController { public function view_active() { $this->set('title_for_layout', 'View Active Users'); $this->layout = 'default_small_ad'; } public function view_image() { $this->layout = 'image'; // 输出用户图像 } }
CakePHP 有两个核心布局(除了 CakePHP 的默认布局之外)供您在自己的应用程序中使用:“ajax”和“flash”。 Ajax 布局便于生成 AJAX 响应 - 这是一个空布局。 (大多数 AJAX 调用只需要返回值中的一点标记,而不是完全呈现的界面。)flash 布局用于方法显示的消息。
其他三个核心(xml、js 和 rss)中的布局以快速、简单的方式提供非文本/html 内容。
使用插件的布局
2.1 新功能。
如果你想使用插件中存在的布局,你可以使用它。 例如,要使用联系人插件中的联系人布局:
class UsersController extends AppController { public function view_active() { $this->layout = 'Contacts.contact'; } }
元素
许多应用程序都有小段的表示代码,这些代码可以在不同的页面上重用,有时在布局中的不同位置上重用。 CakePHP 可帮助您重用网站中您想要重用的部分。 这些可重复使用的部分称为元素。 广告、帮助框、导航控件、附加菜单、登录表单和标注通常使用 CakePHP 中的元素来实现。 元素基本上是一个微型视图,可以引入到其他视图、布局甚至其他元素中。 通过将重复元素的渲染封装到它们自己的文件中,元素的使用可以使视图更具可读性。 它们还可以帮助您在应用程序中重用内容片段。
元素存在于 /app/View/Elements/ 目录中html视图,并具有 .ctp 文件扩展名。 它们是使用视图的元素方法输出的:
echo $this->element('helpbox');
将参数传递给元素
您可以通过 element 方法的第二个参数向元素传递数据:
echo $this->element('helpbox', array( "helptext" => "Oh, this text is very helpful." ));
在元素文件中,所有传入的参数都可以从参数列表成员中获取(与控制器中为视图文件设置参数的方法相同)。 在上面的示例中,/app/View/Elements/helpbox.ctp 文件可以使用 $helptext 变量:
// 在 app/View/Elements/helpbox.ctp 中 echo $helptext; // 输出为 "Oh, this text is very helpful."
该方法还支持元素的配置选项。 支持的选项是“缓存”和“回调”。 例如:
echo $this->element('helpbox', array( "helptext" => "This is passed to the element as $helptext", "foobar" => "This is passed to the element as $foobar", ), array( // 使用"long_view"缓存配置 "cache" => "long_view", // 置为 true, 让元素的 before/afterRender 回调被调用 "callbacks" => true ) );
元素的缓存是通过类完成的。 您可以将元素设置为保存在您设置的任何缓存配置中。 这使您可以非常灵活地决定元素的存储位置和存储时间。 要在应用程序中缓存同一元素的不同版本,请按以下格式提供唯一的缓存通配符:
$this->element('helpbox', array(), array( "cache" => array('config' => 'short', 'key' => 'unique value') ) );
您可以使用 requestAction() 方法来充分利用元素。 requestAction() 方法从控制器操作获取视图变量并将它们作为字段返回。 这允许您的元素以真正的 MVC 方式运行。 创建一个控制器操作以将视图变量分配给您的元素,然后对 element() 的第二个参数调用 requestAction() 以从控制器向元素提供视图变量。
为此,在 Post 情况下,将以下代码添加到控制器中:
class PostsController extends AppController { // ... public function index() { $posts = $this->paginate(); if ($this->request->is('requested')) { return $posts; } $this->set('posts', $posts); } }
然后在元素中我们可以访问分页帖子模型。 要获得最近五个帖子的有序队列,我们可以这样做:
Latest Posts
<?php $posts = $this->requestAction( 'posts/index/sort:created/direction:asc/limit:5' ); ?><?php foreach ($posts as $post): ?> <?php echo $post['Post']['title']; ?> <?php endforeach; ?>
缓存元素
如果您提供缓存参数,则可以利用 CakePHP 的视图缓存。 如果设置为 true,元素将被缓存在“默认”缓存配置中。 否则,您可以设置应使用哪个缓存配置。 有关更多配置信息,请参阅缓存。 这是缓存元素的一个简单示例:
echo $this->element('helpbox', array(), array('cache' => true));
如果您在同一视图中多次渲染同一元素并启用缓存,请记住每次将“key”参数设置为不同的名称。 这可以防止每个后续调用覆盖前一个元素调用的缓存结果。 例如:
echo $this->element( 'helpbox', array('var' => $var), array('cache' => array('key' => 'first_use', 'config' => 'view_long') ); echo $this->element( 'helpbox', array('var' => $differenVar), array('cache' => array('key' => 'second_use', 'config' => 'view_long') );
这将确保两个元素调用的结果被单独缓存。 如果您希望所有元素缓存都使用相同的缓存配置,只需将缓存配置设置为您想要使用的配置即可节省一些重复。 如果没有指定配置,CakePHP 将使用此配置。
从插件请求元素
2.0
要从插件加载元素,请使用plugin选项(从版本1.x中的data选项移出):
echo $this->element('helpbox', array(), array('plugin' => 'Contacts'));
2.1
如果您使用插件并使用插件中的元素,只需使用熟悉的内容即可。 如果为插件中的控制器/操作呈现视图,则使用的所有元素都将手动添加插件名称作为前缀,除非已经有另一个插件名称。 如果该元素不在插件中,则会在主APP目录中搜索。
echo $this->element('Contacts.helpbox');
如果您的视图是插件的一部分,则可以省略插件名称。 例如,如果您在联系人插件的 ContactsController 中,则以下内容:
echo $this->element('helpbox'); // 和 echo $this->element('Contacts.helpbox');
相同并且会导致渲染相同的元素。
版本 2.1 中的修改:不推荐使用 $options[plugin] 选项,并添加对 Plugin.element 的支持。
创建您自己的视图类
您可能需要创建自定义视图类以与新数据视图一起使用,或向应用程序添加其他自定义视图呈现逻辑。 与 CakePHP 的大多数组件一样,视图类也有一些约定:
为此,您应该增强 View:
// 在 App/View/PdfView.php 中 App::uses('View', 'View'); class PdfView extends View { public function render($view = null, $layout = null) { // 这里为定制逻辑。 } }
重写渲染方法使您可以完全控制内容的渲染方式。
查看API
类视图
视图模式在所有视图、元素和布局文件中均可用。 要调用任何视图方法,请使用 $this->method()。
View::set(字符串$var,混合$value)
视图也有一个 set() 方法,就像控制器对象的 set() 方法一样。 在视图文件中使用 set() 方法会将变量添加到随后渲染的布局和元素中。 有关使用 set() 的更多信息,请参阅。
在您的视图文件中您可以:
$this->set('activeMenuButton', 'posts');
然后在您的布局中,变量 $activeMenuButton 将可用,其值为“posts”。
View::get(字符串 $var, $default = null)
获取名为 $var 的视图变量的值。
在 2.5 版本中,您可以提供默认值,以防尚未设置变量。
2.5版本修改:2.5版本降低了$default参数。
查看::getVar(字符串$var)
获取名为 $var 的视图变量的值。
自 2.3 版起已弃用:请使用替代品。
查看::getVars()
获取当前渲染范围内可以使用的所有视图变量的列表,并返回变量名称的链表。
View::element(字符串 $elementPath, 数组 $data, 数组 $options = array())
渲染元素或视图片段。 有关更多信息和示例,请参阅部分。
View::uuid(字符串$object,混合$url)
根据对象的类型和 URL 生成唯一的、非随机的 DOM ID。 需要为 HTML 元素生成唯一 DOM ID 的帮助程序经常使用此方法html视图,如下所示:
$uuid = $this->uuid( 'form', array('controller' => 'posts', 'action' => 'index') ); // $uuid 含有 'form0425fe3bad'
View::addScript(字符串$名称,字符串$内容)
将内容添加到内部脚本缓冲区。 可以使用 $scripts_for_layout 在布局中访问此缓冲区。 当创建需要将 JavaScript 或 CSS 直接添加到布局的帮助程序时,此技术非常有用。 请记住,从布局或布局中的元素添加的脚本不会添加到 $scripts_for_layout。 此方法最常在帮助程序中使用,例如 JsHelper 和 HtmlHelper 帮助程序。
自 2.1 版起已弃用:请不要再使用它,而是使用它。
查看::块()
获取以链接列表表示的所有已定义代码块的名称。
查看::开始($name)
开始查看代码块的捕获块。 请参阅部分示例。
2.1 新功能。
查看::结束()
结束最近开始的捕获块。 请参阅部分示例。
2.1 新功能。
查看::append($名称,$内容)
附加在由 $name 命名的代码块的末尾。 请参阅部分示例。
2.1 新功能。
查看::前置($名称,$内容)
添加到以 $name 命名的代码块的开头。 请参阅部分示例。
2.3 新功能。
查看::startIfEmpty($name)
仅当代码块为空时才会启动。 如果代码块已经被定义,则代码块的全部内容(此处定义)将被捕获并丢弃。
2.3 新功能。
查看::分配($名称,$内容)
给出一个代码块参数。 这将覆盖任何现有内容。 请参阅部分示例。
2.1 新功能。
查看::fetch($name, $default = '')
获取代码块的值。 如果代码块为空或未定义,则返回 ''。 请参阅部分示例。
2.1 新功能。
查看::扩展($name)
使用命名视图/元素/布局扩展当前视图/元素/布局。 请参阅部分示例。
2.1 新功能。
属性视图::$布局
设置用于包含当前视图的布局。
属性视图::$elementCache
用于缓存元素的缓存配置。 设置此属性将更改用于缓存元素的默认配置。 可以使用元素方法中的“cache”选项更改默认值(缓存配置)。
属性视图::$请求
的一个实例。 使用此实例获取有关当前请求的信息。
属性视图::$输出
包含视图先前渲染的内容,可以是视图文件或布局内容。
自 2.1 版起已弃用:请不要再使用它,请使用 $view->Blocks->get('content'); 反而。
属性视图::$Blocks
ViewBlock 的实例。 用于视图渲染,提供视图代码块功能。
2.1 新功能。
发表评论