加载中...

快速入门 18:多层控制器


ThinkPHP支持多层业务控制器的支持,给中大型应用提供了方便。

定义多层控制器

我们通常所了解的控制器其实是Controller控制器类,而且大多数也是继承了核心的Think\Controller类,由于该类控制器是通过URL访问请求后调用的,因此也称之为访问控制器,事实上,ThinkPHP可以支持更多的控制器分层,多层控制器的定义完全取决于项目的需求,例如我们可以分为业务控制器和事件控制器:

Home\Controller\UserController //用于用户的业务逻辑控制和调度
Home\Event\UserEvent //用于用户的事件响应操作

  1. ├─Controller 访问控制器
  2. ├─UserController.class.php
  3. ...
  4. ├─Event 事件控制器
  5. ├─UserEvent.class.php
  6. ...

一个标准的访问控制器定义如下:

  1. namespace Home\Controller;
  2. class UserController extend Think\Controller {
  3. // 默认操作方法
  4. public function index(){
  5. //...
  6. }
  7. // 用户注册操作方法
  8. public function register(){
  9. //...
  10. }
  11. }

注:访问控制器的名称并非一定是Controller,而是通过DEFAULT_C_LAYER设置的,默认设置是Controller。

访问控制器负责外部的交互响应,通过URL请求调用,例如:

  1. http://serverName/Home/User/index
  2. http://serverName/Home/User/register

而事件控制器负责内部的事件响应,并且只能在内部调用,所以是和外部隔离的。

确切的说,所有访问控制器之外的分层控制器都只能内部实例化调用。

  1. namespace Home\Event;
  2. class UserEvent {
  3. // 用户登录事件
  4. public function login(){
  5. echo 'login event';
  6. }
  7. // 用户登出事件
  8. public function logout(){
  9. echo 'logout event';
  10. }
  11. }

如果是定义其他的控制器层,则不一定必须要继承系统的Controller类或其子类,通常需要输出模版的时候才需要继承Controller类。

调用多层控制器

访问控制器是通过URL请求调用,访问控制器之外的分层控制器都只能内部调用,调用多层控制器可以通过两种方式:

直接实例化

  1. namespace Home\Controller;
  2. class UserController extend Think\Controller {
  3. // 默认操作方法
  4. public function index(){
  5. // 触发事件
  6. $event = new \Home\Event\UserEvent();
  7. $event->login();
  8. }
  9. }

A函数实例化

  1. namespace Home\Controller;
  2. class UserController extend Think\Controller {
  3. // 默认操作方法
  4. public function index(){
  5. // 触发事件
  6. $event = A('User','Event');
  7. $event->login();
  8. // 或者直接使用
  9. // R('User/login','','Event');
  10. }
  11. }

Widget实例

Widget类的实现可以作为分层控制器的另外一个典型实例。

举个例子,我们在页面中实现一个分类菜单的Widget,首先我们要定义一个Widget控制器层 MenuWidget,如下:

  1. namespace Home\Widget;
  2. class MenuWidget extends Think\Controller {
  3. public function index(){
  4. echo 'menuWidget';
  5. }
  6. }

类文件位于 Home/Widget/MenuWidget.class.php

然后,我们在需要显示分类菜单的模版中通过W方法调用这个Widget。

  1. {~W('Menu/index')}

执行后的输出结果是: menuWidget

如果需要在调用Widget的时候传入参数,可以这样定义:

  1. namespace Home\Widget;
  2. class MenuWidget extends Think\Controller {
  3. public function index($id,$name){
  4. echo $id.':'.$name;
  5. }
  6. }

在需要显示分类菜单的模版中添加如下的Widget调用代码如下:

  1. {~W('Menu/index',array(5,'thinkphp'))}

则会输出 5:thinkphp

来一个复杂一点的例子:

  1. namespace Home\Widget;
  2. class MenuWidget extends Think\Controller {
  3. public function index(){
  4. $menu = M('Cate')->getField('id,title');
  5. $this->assign('menu',$menu);
  6. $this->display('Widget/menu');
  7. }
  8. }

CateWiget类渲染了一个模版文件 Home/View/Widget/menu.html,
在menu.html模版文件中的用法:

  1. <foreach name="menu" item="title">
  2. {$key}:{$title}
  3. </foreach>

还没有评论.