TP5的控制器定义比较灵活,可以无需继承任何的基础类,也可以继承官方封装的\think\Controller类或其他的控制器类。

1、控制器定义

一个典型的控制器类定义如下:

namespace app\index\controller;class Index
{public function index(){return 'index';}
}

控制器类文件的实际位置是

application\index\controller\Index.php

控制器类可以无需继承任何类,命名空间默认以app为根命名空间。

控制器的根命名空间可以设置,例如我们在应用配置文件中修改:

// 修改应用类库命名空间
'APP_NAMESPACE' => 'application',

则实际的控制器类应该更改定义如下:

namespace application\index\controller;class Index
{public function index(){return 'index';}
}

只是命名空间改变了,但实际的文件位置和文件名并没有改变。

使用该方式定义的控制器类,如果要在控制器里面渲染模板,可以使用

namespace app\index\controller;use think\View;class Index
{public function index(){$view = new View();return $view->fetch('index');}
}

或者直接使用view助手函数渲染模板输出,例如:

namespace app\index\controller;class Index
{public function index(){return view('index');}
}

如果继承了think\Controller类的话,可以直接调用think\View及think\Request类的方法,例如:

namespace app\index\controller;use think\Controller;class Index extends Controller
{public function index(){// 获取包含域名的完整URL地址$this->assign('domain',$this->request->url(true));return $this->fetch('index');}
}

渲染输出

默认情况下,控制器的输出全部采用return的方式,无需进行任何的手动输出,系统会自动完成渲染内容的输出。

下面都是有效的输出方式:

namespace app\index\controller;class Index
{public function hello(){return 'hello,world!';}public function json(){return json_encode($data);}public function read(){return view();}}

控制器一般不需要任何输出,直接return即可。

默认情况下,控制器的返回输出不会做任何的数据处理,但可以设置输出格式,并进行自动的数据转换处理,前提是控制器的输出数据必须采用return的方式返回。

如果控制器定义为:

namespace app\index\controller;class Index
{public function hello(){return 'hello,world!';}public function data(){return ['name'=>'thinkphp','status'=>1];}}

当我们设置输出数据格式为JSON:

// 默认输出类型
'default_return_type'   => 'json',

我们访问

http://localhost/index.php/index/Index/hello
# "hello,world!"
http://localhost/index.php/index/Index/data
# {"name":"thinkphp","status":1}

默认情况下,控制器在ajax请求会对返回类型自动转换,默认为json

如果我们控制器定义

namespace app\index\controller;class Index
{public function data(){return ['name'=>'thinkphp','status'=>1];}}

我们访问

http://localhost/index.php/index/Index/data
# {"name":"thinkphp","status":1}

当我们设置输出数据格式为html:

// 默认输出类型
'default_ajax_return'   => 'html',

这种情况下ajax请求不会对返回内容进行转换。

2、控制器初始化

如果控制器类继承了\think\Controller类的话,可以定义控制器初始化方法_initialize,在该控制器的方法调用之前首先执行。

namespace app\index\controller;use think\Controller;class Index extends Controller
{public function _initialize(){echo 'init<br/>';}public function hello(){return 'hello';}public function data(){return 'data';}
}

如果访问

http://localhost/index.php/index/Index/hello
# init
# hello

3、前置操作

可以为某个或者某些操作指定前置执行的操作方法,设置 beforeActionList属性可以指定某个方法为其他方法的前置操作,数组键名为需要调用的前置方法名,无值的话为当前控制器下所有方法的前置方法。

['except' => '方法名,方法名']

表示这些方法不使用前置方法,

['only' => '方法名,方法名']

表示只有这些方法使用前置方法。

示例如下:

namespace app\index\controller;use think\Controller;class Index extends Controller
{protected $beforeActionList = ['first','second' =>  ['except'=>'hello'],'three'  =>  ['only'=>'hello,data'],];protected function first(){echo 'first<br/>';}protected function second(){echo 'second<br/>';}protected function three(){echo 'three<br/>';}public function hello(){return 'hello';}public function data(){return 'data';}
}

访问

http://localhost/index.php/index/Index/hello
# first
# three
# hello

访问

http://localhost/index.php/index/Index/data
# first
# second
# three
# data

4、页面跳转

页面跳转

\think\Controller类内置了两个跳转方法success和error,用于页面跳转提示

namespace app\index\controller;use think\Controller;
use app\index\model\User;class Index extends Controller
{public function index(){$User = new User; //实例化User对象$result = $User->save($data); if($result){//设置成功后跳转页面的地址,默认的返回页面是$_SERVER['HTTP_REFERER']$this->success('新增成功', 'User/list');} else {//错误页面的默认跳转页面是返回前一页,通常不需要设置$this->error('新增失败');}}
}

跳转地址是可选的,success方法的默认跳转地址是$_SERVER[“HTTP_REFERER”],error方法的默认跳转地址是
javascript:history.back(-1);。

默认的等待时间都是3秒

success和error方法都可以对应的模板,默认的设置是两个方法对应的模板都是:

THINK_PATH . 'tpl/dispatch_jump.tpl'

可以改变默认的模板:

//默认错误跳转对应的模板文件
'dispatch_error_tmpl' => APP_PATH . 'tpl/dispatch_jump.tpl',
//默认成功跳转对应的模板文件
'dispatch_success_tmpl' => APP_PATH . 'tpl/dispatch_jump.tpl',

模板文件可以使用模板标签,并且可以使用下面的模板变量:

error方法会自动判断当前请求是否属于Ajax请求,如果属于Ajax请求则会自动转换为default_ajax_return配置的格式返回信息。 success在Ajax请求下不返回信息,需要开发者自行处理。

重定向

\think\Controller类的redirect方法可以实现页面的重定向功能。

redirect方法的参数用法和Url::build方法的用法一致(参考URL生成部分),例如:

//重定向到News模块的Category操作
$this->redirect('News/category', ['cate_id' => 2]);

上面的用法是跳转到News模块的category操作,重定向后会改变当前的URL地址。

或者直接重定向到一个指定的外部URL地址,例如:

//重定向到指定的URL地址 并且使用302
$this->redirect('http://thinkphp.cn/blog/2',302);

可以在重定向的时候通过session闪存数据传值,例如

$this->redirect('News/category', ['cate_id' => 2], 302, ['data' => 'hello']);

使用redirect助手函数还可以实现更多的功能,例如可以记住当前的URL后跳转

redirect('News/category')->remember();

需要跳转到上次记住的URL的时候使用:

redirect()->restore();

跳转和重定向的URL地址不需要再使用url方法进行生成,会自动调用,请注意避免,否则会导致多次生成而出现两个重复的URL后缀

5、空操作

空操作是指系统在找不到指定的操作方法的时候,会定位到空操作(_empty)方法来执行,利用这个机制,我们可以实现错误页面和一些URL的优化。
例如,下面我们用空操作功能来实现一个城市切换的功能。

我们只需要给City控制器类定义一个_empty (空操作)方法:

<?php
namespace app\index\controller;class City
{public function _empty($name){//把所有城市的操作解析到city方法return $this->showCity($name);}//注意 showCity方法 本身是 protected 方法protected function showCity($name){//和$name这个城市相关的处理return '当前城市' . $name;}
}

接下来,我们就可以在浏览器里面输入

http://serverName/index/city/beijing/
http://serverName/index/city/shanghai/
http://serverName/index/city/shenzhen/

由于City并没有定义beijing、shanghai或者shenzhen操作方法,因此系统会定位到空操作方法 _empty中去解析,_empty方法的参数就是当前URL里面的操作名,因此会看到依次输出的结果是:

当前城市:beijing
当前城市:shanghai
当前城市:shenzhen

V5.0.2+开始,空操作方法不需要任何参数,如果要获取当前的操作方法名,直接调用当前请求对象来获取,你也可以使用依赖注入

6、空控制器

空控制器的概念是指当系统找不到指定的控制器名称的时候,系统会尝试定位空控制器(Error),利用这个机制我们可以用来定制错误页面和进行URL的优化。

现在我们把前面的需求进一步,把URL由原来的

http://serverName/index/city/shanghai/

变成

http://serverName/index/shanghai/

这样更加简单的方式,如果按照传统的模式,我们必须给每个城市定义一个控制器类,然后在每个控制器类的index方法里面进行处理。 可是如果使用空控制器功能,这个问题就可以迎刃而解了。

我们可以给项目定义一个Error控制器类

<?php
namespace app\index\controller;use think\Request;class Error
{public function index(Request $request){//根据当前控制器名来判断要执行那个城市的操作$cityName = $request->controller();return $this->city($cityName);}//注意 city方法 本身是 protected 方法protected function city($name){//和$name这个城市相关的处理return '当前城市' . $name;}
}

接下来,我们就可以在浏览器里面输入

http://serverName/index/beijing/
http://serverName/index/shanghai/
http://serverName/index/shenzhen/

由于系统并不存在beijing、shanghai或者shenzhen控制器,因此会定位到空控制器(Error)去执行,会看到依次输出的结果是:

当前城市:beijing
当前城市:shanghai
当前城市:shenzhen

空控制器和空操作还可以同时使用,用以完成更加复杂的操作。

空控制器Error是可以定义的

// 更改默认的空控制器名
'empty_controller'      => 'MyError',

当找不到控制器的时候,就会定位到MyError控制器类进行操作。

7、多级控制器

新版支持任意层次级别的控制器,并且支持路由,例如:

namespace app\index\controller\one;use think\Controller;class Blog extends Controller
{public function index(){return $this->fetch();}public function add(){return $this->fetch();}public function edit($id){return $this->fetch();}
}

该控制器类的文件位置为:

application/index/controller/one/Blog.php

访问地址可以使用

http://serverName/index.php/index/one.blog/index

如果要在路由定义中使用多级控制器,可以使用:

\think\Route::get('blog/add','index/one.Blog/add');

8、分层控制器

访问控制器

TP5引入了分层控制器的概念,通过URL访问的控制器为访问控制器层(Controller)或者主控制器,访问控制器是由\think\App类负责调用和实例化的,无需手动实例化。

URL解析和路由后,会把当前的URL地址解析到 [ 模块/控制器/操作 ],其实也就是执行某个控制器类的某个操作方法,下面是一个示例:

namespace app\index\controller;class Blog
{public function index(){return 'index';}public function add(){return 'add';}public function edit($id){return 'edit:'.$id;}
}

当前定义的主控制器位于index模块下面,所以当访问不同的URL地址的页面输出如下:

http://serverName/index/blog/index // 输出 index
http://serverName/index/blog/add     // 输出 add
http://serverName/index/blog/edit/id/5 // 输出 edit:5

新版的控制器可以不需要继承任何基类,当然,你可以定义一个公共的控制器基础类来被继承,也可以通过控制器扩展来完成不同的功能(例如Restful实现)。

如果不经过路由访问的话,URL中的控制器名会首先强制转为小写,然后再解析为驼峰法实例化该控制器。

分层控制器

除了访问控制器外,我们还可以定义其他分层控制器类,这些分层控制器是不能够被URL访问直接调用到的,只能在访问控制器、模型类的内部,或者视图模板文件中进行调用。

例如,我们定义Blog事件控制器如下:

namespace app\index\event;class Blog
{public function insert(){return 'insert';}public function update($id){return 'update:'.$id;}public function delete($id){return 'delete:'.$id;}
}

定义完成后,就可以用下面的方式实例化并调用方法了:

$event = \think\Loader::controller('Blog', 'event');
echo $event->update(5); // 输出 update:5
echo $event->delete(5); // 输出 delete:5

为了方便调用,系统提供了controller助手函数直接实例化多层控制器,例如:

$event = controller('Blog', 'event');
echo $event->update(5); // 输出 update:5
echo $event->delete(5); // 输出 delete:5

支持跨模块调用,例如:

$event = controller('Admin/Blog', 'event');
echo $event->update(5); // 输出 update:5

表示实例化Admin模块的Blog控制器类,并执行update方法。

除了实例化分层控制器外,还可以直接调用分层控制器类的某个方法,例如:

echo \think\Loader::action('Blog/update', ['id' => 5], 'event'); // 输出 update:5

也可以使用助手函数action实现相同的功能:

echo action('Blog/update', ['id' => 5], 'event'); // 输出 update:5

利用分层控制器的机制,我们可以用来实现Widget(其实就是在模板中调用分层控制器),例如:

定义index\widget\Blog控制器类如下:

namespace app\index\widget;class Blog {public function header(){return 'header';}public function left(){return 'left';}public function menu($name){return 'menu:'.$name;}
}

在模板文件中就可以直接调用app\index\widget\Blog分层控制器了,
使用助手函数action

{:action('Blog/header', '', 'widget')}
{:action('Blog/menu', ['name' => 'think'], 'widget')}

框架还提供了widget函数用于简化Widget控制器的调用,
可以直接使用助手函数widget

{:widget('Blog/header')}
{:widget('Blog/menu', ['name' => 'think'])}

9、自动定位控制器

如果使用了多级控制器的话,可以设置controller_auto_search参数开启自动定位控制器,便于URL访问,例如首先在配置文件中添加:

'controller_auto_search' => true,

然后定义控制器如下:

namespace app\index\controller\one;use think\Controller;class Blog extends Controller
{public function index(){return $this->fetch();}public function add(){return $this->fetch();}public function edit($id){return $this->fetch('edit:'.$id);}
}

然后就可以直接访问下面的URL地址了:

http://serverName/index.php/index/one/Blog

10、资源控制器

资源控制器可以让你轻松的创建RESTFul资源控制器,可以通过命令行生成需要的资源控制器,例如:

// 生成index模块的Blog资源控制器
php think make:controller index/Blog

或者使用完整的命名空间生成

php think make:controller app\index\controller\Blog

然后只需要为资源控制器注册一个资源路由:

Route::resource('blog','index/Blog');

设置后会自动注册7个路由规则,如下:

TP5学习(四):控制器相关推荐

  1. (转)SpringMVC学习(四)——Spring、MyBatis和SpringMVC的整合

    http://blog.csdn.net/yerenyuan_pku/article/details/72231763 之前我整合了Spring和MyBatis这两个框架,不会的可以看我的文章MyBa ...

  2. C#多线程学习(四) 多线程的自动管理(线程池) (转载系列)——继续搜索引擎研究...

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  3. python学习四(处理数据)

    python学习四(处理数据) head first python中的一个数据处理的例子 有四个U10选手的600米成绩,请取出每个选手跑的最快的3个时间.以下是四位选手的9次成绩 James 2-3 ...

  4. PyTorch框架学习四——计算图与动态图机制

    PyTorch框架学习四--计算图与动态图机制 一.计算图 二.动态图与静态图 三.torch.autograd 1.torch.autograd.backward() 2.torch.autogra ...

  5. Docker学习四:Docker 网络

    前言 本次学习来自于datawhale组队学习: 教程地址为: https://github.com/datawhalechina/team-learning-program/tree/master/ ...

  6. 算法学习四:算法性能分析理论基础——函数增长与渐进分析

    算法学习四:算法性能分析理论基础--函数增长与渐进分析 在算法性能分析过程中,特别是在算法运行效率分析中,我们经常使用渐渐分析法,它使我们在分析算法性能时不必纠结于不同硬件平台的差异性,着重考虑算法的 ...

  7. Tensorflow学习四---高阶操作

    Tensorflow学习四-高阶操作 Merge and split 1.tf.concat 拼接 a = tf.ones([4,32,8]) b = tf.ones([2,32,8]) print( ...

  8. [jQuery学习系列四 ]4-Jquery学习四-事件操作

    [jQuery学习系列四 ]4-Jquery学习四-事件操作 前言: 今天看知乎偶然看到中国有哪些类似于TED的节目, 回答中的一些推荐我给记录下来了, 顺便也在这里贴一下: 一席 云集 听道 推酷 ...

  9. AVI音视频封装格式学习(四)——linux系统C语言AVI格式音视频封装应用

    拖了很久的AVI音视频封装实例,花了一天时间终于调完了,兼容性不是太好,但作为参考学习使用应该没有问题.RIFF和AVI以及WAV格式,可以参考前面的一些文章.这里详细介绍将一个H264视频流和一个2 ...

  10. C1认证学习四(多媒体基础参数)

    C1认证学习四(多媒体基础参数) 文章目录 C1认证学习四(多媒体基础参数) 任务学习 任务目标 参数的定义 比特率 采样率 采样位深 任务学习 所谓的多媒体指的是多种媒体的综合,一般都包含有图像.声 ...

最新文章

  1. 英特尔90亿美元卖掉「起家业务」,SK海力士接盘
  2. BZOJ4004: [JLOI2015]装备购买
  3. QuickBI助你成为分析师-邮件定时推送
  4. 【WEB API项目实战干货系列】- 接口文档与在线测试(二)
  5. C语言 NULL 和 0 区别 - C语言零基础入门教程
  6. Javascript中最常用的经典技巧
  7. Linux下多线程调试以及查看信息
  8. 代码整洁之道读书笔记----第二章---命名--第一节-名副其实
  9. 恒强制版系统980_恒强制版软件操作答疑
  10. python用均值填充空值_用平均值填充空值
  11. 中国雅虎邮箱明日停止服务 邮件帐户均将删除
  12. Nvidia驱动支持的linux版本,NVIDIA首发OpenGL 3.1驱动 全面支持Linux
  13. 后台获取用户登录信息
  14. 微软快捷键截图_所有最好的Microsoft Excel键盘快捷键
  15. python产品质量分析报告范文_Python Jinja2 徒手生成数据分析报告
  16. 【高自旋和低自旋配合物】
  17. Xmanager 5问题记录
  18. 【爬虫系列】Python 爬虫入门(2)
  19. 面向对象划分--ERP销售订单、生产工单、料号
  20. paypal电汇使用心得

热门文章

  1. html form 里加图片,上传图片HTML form 标签的 method 属性
  2. 【python】python基础测试100题
  3. 剪映导出帧率选多少_自媒体视频剪辑:巧影导出视频时如何设置参数?分辨率、帧率、码率该如何选择...
  4. Team Leader
  5. Python爬虫,爬取二次元萌妹图片(可自由设定图片像素)
  6. imx6ull uboot nfs Loading* done异常
  7. Map的几种循环方法
  8. Smartbi电子表格常用设置
  9. 全国计算机一级电子表格教程,全国计算机等级考试一级教程-Excel的使用(93页)-原创力文档...
  10. H5移动端 iOS / Android 兼容性总结