控制器是 MVC 中的 ‘C’ 。在应用了路由且正确的控制器被找到之后,控制器的动作(action)被调用。控制器将处理解释请求数据,确保正确的模型被调用,确保正确的输出或视图被渲染。控制器可被视为模型和视图的中间人。你要保持控制器很精炼,而模型类很丰满。这会帮助你更容易地重用你的代码,并使你的代码更易于测试。
通常,控制器用于管理单个视图逻辑。例如,你为一个在线面包店建立站点,你可能会有一个 RecipesController 和一个 IngredientsController,管理你的食谱和原料。在 CakePHP 中,控制器用它们处理的主要模型命名。也常常会有一个控制器和多个模型共同工作的情况。
应用程序控制器扩展自 AppController 类,它扩展自内核的 Controller 类。AppController 类可以在/app/Controller/AppController.php 中定义,它可以包含应用程序中多个控制器共享的方法。
控制器提供的一些方法被叫做 动作(actions)。动作是控制器用来处理请求的方法。默认情况下,控制器中所有的公有方法都可以从 url 访问。控制器负责解析请求并创建响应。通常响应是以渲染视图的格式完成,但有时也会用其它途径创建响应。
诚如介绍中所言,AppController 类是所有应用程序控制器的你类。 AppController 自身是扩展自 CakePHP 核心库中的 Controller 类。 /app/Controller/AppController.php 文件中的 AppController 类类似于:
AppController 中建立的属性和方法在应用程序的所有控制器中都可用。 它是放置所有控制器的公用代码的最佳位置。 组件(你将会有后面学到)则用于存放许多控制器(但不一定是全部)都使用的代码。
相对于正常的面向对象继承规则,CakePHP 对于控制器的特殊属性,做了一些扩展工作。组件和助手清单被控制器特殊对待。 在这些情况下,AppContrller 值数组和子控制器类的数组合并。子类的那些值总是覆盖 AppController 类的同名值。
注解
CakePHP 合并 AppController 和你的应用程序控制器的如下变量:
如果你在 AppController 中定义了 $helpers ,记得添加默认的 Html 和 Form 助手。
还要记得在子类的回调方法中调用 AppController 的回调方法。
请求参数
在为 CakePHP 应用程序生成了请求之后,CakePHP 的 Router 和 Dispatcher 类使用 路由配置 寻找和建立正确的控制器。请求数据压入一个请求对象。CakePHP 把所有重要的请求信息都放入 $this->request 属性。关于 CakePHp 请求对象的更多信息请参看 CakeRequest 。
控制器负责将请求参数转换成浏览器/用户要求的响应。CakePHP 使用约定自动完成这些处理过程并移动了在其它情况下你需要编写的一些程式化的代码。
根据约定,CakePHP 渲染一个动作名映射的视图。回到我们的在线面包店的例子,我们的 RecipesController 可能会包含 view()、share() 和 search() 动作。这个控制器在 /app/Controller/RecipesController.php 文件中,并且包含如下内容:
这些动作对应的视图文件分别是 app/View/Recipes/view.ctp、 app/View/Recipes/share.ctp 和 andapp/View/Recipes/search.ctp。视图文件名被规定为使用小写和下划线间隔的版本的动作名。
控制器动作通常使用 set() 来创建用于渲染视图瓣 View 上下文。 由于使用 CakePHP 的约定,你不需要手动创建和渲染视图。取而代之的是,一旦一个应用程序的动作完成,CakePHP 将处理视图渲染和传输。
某些情况下你可能需要跳过默认的的行为。下面的技巧可以跳过默认的视图渲染。
控制器方法使用 requestAction() 处理你想返回的非字符串数据。如果你的控制器方法使用 常规请求 + requestAction,你需要在运行前检查请求的类型:
上面的控制器动作是如何在一个方法中使用 requestAction() 和常规请求。给非 requestActin 请求返回一个数组将引起错误,这是需要的避免的。关于使用 requestAction() 的更多提示请参阅 Controller::requestAction() 环节。
为使你在应用程序中更有效地使用控制器,我们提供了 CakePHP 控制器常用的一些核心属性和方法。
CakePHP 控制器提供了能用来在请求生命周期中插入逻辑的回调:
这个函数在控制器中的每个动作前执行。 它是检验活动会话或用户授权验证的好地方。
注解
beforeFilter() 方法在找不到动作时或者脚手架动作执行前,也会执行。
在控制器动作逻辑之后、视图渲染前调用。这个回调不常用,但是如果你在动作结束前手动调用 render() 时可能会需要它。
在控制器动作逻辑和渲染完成之后调用。这是运行时执行的最后一个控制器方法。
除了控制器周期回调之外,组件 也提供一组回调集。
完整的控制器方法列表及其描述请访问 CakePHP API,浏览 http://api20.cakephp.org/class/controller。
控制器与视图交互有几种方法。 首先,可以使用 set() 向视图传送数据。还可以决定使用哪个视图类,以及在控制器中渲染哪个视图文件。
set() 方法是从控制器向视图传送数据的主要途径。一旦你使用 set() ,就可以在视图中访问这些变量:
set() 方法还能将它的第一个参数设成一个关联数组。这是在视图中访问信息集合时常用的方法。
在 1.3 版更改: 数组的键在被赋值到视图前将不会被改变(例如,’underscored_key’ 不再会变成 ‘underscoredKey’):
属性 $pageTitle 不存在,使用 set() 设置标题:
Controller::render(string $action, string $layout, string $file)
render() 在每个被请求的控制器动作结束前被自动调用。此方法执行所有的视图逻辑(使用通过 set() 方法提供的数据),将视图放进它的布局中,并且将其提供给最终用户。
被渲染的默认视图文件根据约定来决定。 如果 RecipesController 的 search() 动作被请求,此视图文件 /app/View/Recipes/search.ctp 被渲染:
虽然 CakePHP 将在每个动作逻辑之后自动调用它(直到你将 $this->autoRender 设置为 false),但是你可以通过在控制器中使用 $action 指定另一个视图文件。
如果 $action 以 ‘/’ 开头,视图文件或元素文件就以 /app/View 作为起始位置定位。这将允许元素渲染转向,在 ajax 调用中非常有用。:
你还可以使用第三个参数 $file 指定另一个视图或者元素文件。 $layout 参数允许你指定视图在哪个布局中渲染。
在控制器中,你能够渲染与约定不一样的视图。通过调用 render() 来实现这一目的。一旦你调用了 render(),CakePHP就不再试图重新渲染默认的视图了。