在上一课程中, 你可能会对 ThinkPHP 的路由会有一丝丝疑惑, 不过没关系, 学完本课程, 很多事都会豁然开朗
控制器文件命名遵守 IndexController.class.php 的方式
控制器的定义
在开始之前, 我们还是需要明确一下控制器的定义:
- <?php
- namespace Home\Controller;
- use Think\Controller;
- class IndexController extends Controller {public function read($id){
- echo "read page with" .$id;
- }
- public function top(){
- echo "top page";
- }
- }
如所见, 前面在路由篇提到的控制器就是这么定义的:
使用相应的命名空间, 默认是 namespace Home\Controller
加载 Think\Controller
新建控制器继承于 Controller(或子类)
采用驼峰命名法, 注意首字母大写
控制器内的公共方法可以看作一个操作, 比如上面的 read()和 top()方法就可以看作操作, 我们在路由篇的时候都验证过了
http://localhost:8999/index.php/Home/Index/top
就是访问到 top()方法, 会在页面上打印出 top page , 再次明确 Home 代表的是 Home 模块
有时候可能会遇到有和系统的关键字冲突的方法, 这时候就可以使用设置操作方法后缀来解决了, 具体请看官方文档:
http://document.thinkphp1.cn/manual_3_2.html#define_controller
前置和后置操作
前置和后置操作指的是在执行某个操作方法之前和之后会自动调用的方法, 不过仅对访问控制器有效, 如在 IndexController 中为 top()方法添加前置后置方法:
- public function _before_top(){
- echo "before top page";
- }
- public function top(){
- echo "top page";
- }
- public function _after_top(){
- echo "after top page";
- }
访问: http://localhost:8999/index.php/Home/Index/top
就会看到打印出:
- before top page
- top page
- after top page
使用前置和后置操作要注意如下两点:
如果当前的操作并没有定义操作方法, 而是直接渲染模板文件, 那么如果定义了前置和后置方法的话, 依然会生效真正有模板输出的可能仅仅是当前的操作, 前置和后置操作一般情况是没有任何输出的
需要注意的是, 在有些方法里面使用了 exit 或者错误输出之类的话 有可能不会再执行后置方法了例如, 如果在当前操作里面调用了系统 Action 的 error 方法, 那么将不会再执行后置操作, 但是不影响 success 方法的后置方法执行
可以用于表单的过滤和验证
参数绑定
参数绑定是通过直接绑定 URL 地址中的变量作为操作方法的参数, 可以简化方法的定义甚至路由的解析
'URL_PARAMS_BIND' => true
参数绑定功能默认是开启的, 其原理是把 URL 中的参数 (不包括模块控制器和操作名) 和操作方法中的参数进行绑定
参数绑定有两种方式: 按照变量名绑定和按照变量顺序绑定, 默认使用的是按照变量名绑定, 比如看下面的例子:
- public function read($id){
- echo "read page with".$id;
- }
- public function archive($year, $month){
- echo "$year".$month;
- }
对, 这个就是上一篇路由所涉及的内容, 在之前路由的路由设置处
'blogs/:id' => array('Index/read')
我们将: id 直接映射给 read()方法的参数 $id, 所以现在回头再看, 其实路由规则就是给了你一个自定义 URL 的功能如果去掉上面的路由设置, 我们正确的访问方式是:
http://localhost:8999/Home/index/read/id/3
上面的 URl 中 id 就是变量名, 如果你写成:
- public function read($title){
- echo "read page with".$title;
- }
那么访问地址就是:
http://localhost:8999/index.php/Home/index/read/title/3
对于多个参数绑定的情况, 只要将相应的变量名和值传进来就可以了, 不在乎顺序, 比如下面两个会返回相同的结果:
- http://localhost:8999/index.php/Home/index/archive/year/2012/month/12
- http://localhost:8999/index.php/Home/index/archive/month/12/year/2012
需要注意的是, 不管那种情况之下, 当你访问
http://localhost:8999/index.php/Home/index/read/
是会报错的:
参数错误或者未定义: id
解决的一个好方法就是, 给绑定的参数设置默认值, 比如:
- public function read($id=0){
- echo "read page with".$id;
- }
这样再次访问上面的 URL, 就会输出:
read page with
0
tips: 给绑定参数设置默认值是一个避免报错的好办法
在实际的开发中, 我们其实会见到没有显示变量名这样的 URL, 如:
http://localhost:8999/index.php/Home/index/read/3
怎么解决呢? 这个时候, 我们其实就可以用到第二种参数绑定: 按照变量顺序绑定要使用这种参数绑定, 需要先在设置项中设置:
'URL_PARAMS_BIND_TYPE' => 1
一旦设置变量顺序绑定, 这种情况下 URL 地址中的参数顺序非常重要, 不能随意调整这种情况下操作方法的定义不需要改变, 只是访问的 URL 变了而已, 现在用上面的方式访问就可以正确访问了
如果在变量顺序绑定的情况下, 我们访问:
- http://localhost:8999/index.php/Home/index/archive/2012/12
- http://localhost:8999/index.php/Home/index/archive/12/2012
这两个结果显然是不一样, 后者并不是我们想要的所以这种情况需要严格遵守顺序来传值
伪静态
URL 伪静态通常是为了满足更好的 SEO 效果, ThinkPHP 支持伪静态 URL 设置, 可以通过设置 URL_HTML_SUFFIX 参数随意在 URL 的最后增加你想要的静态后缀, 而不会影响当前操作的正常执行, 默认情况下, 伪静态的设置为 html 但我们可以自己设置, 例如
'URL_HTML_SUFFIX'=>'shtml'
如果希望支持多个伪静态后缀, 可以直接设置如下:
'URL_HTML_SUFFIX' => 'html|shtml|xml'
如果此项设置留空则表示可以支持所有的静态后缀
也可以设置禁止访问的 URL 后缀通过 URL_DENY_SUFFIX 来设置, 例如:
'URL_DENY_SUFFIX' => 'pdf|ico|png|gif|jpg',
注: URL_DENY_SUFFIX 的优先级比 URL_HTML_SUFFIX 要高
URL 生成
为了配合所使用的 URL 模式, 我们需要能够动态的根据当前的 URL 设置生成对应的 URL 地址, 为此, ThinkPHP 内置提供了 U 方法, 用于 URL 的动态生成, 可以确保项目在移植过程中不受环境的影响
定义规则
U 方法的定义规则如下(方括号内参数根据实际应用决定):
U('地址表达式',['参数'],['伪静态后缀'],['显示域名'])
地址表达式
地址表达式的格式定义如下:
[模块 / 控制器 / 操作 #锚点 @域名]? 参数 1 = 值 1 & 参数 2 = 值 2...
如果不定义模块的话 就表示当前模块名称, 下面是一些简单的例子:
- U('User/add') // 生成 User 控制器的 add 操作的 URL 地址
- U('Article/read?id=1') // 生成 Article 控制器的 read 操作 并且 id 为 1 的 URL 地址
- U('Admin/User/select') // 生成 Admin 模块的 User 控制器的 select 操作的 URL 地址
参数
U 方法的第二个参数支持数组和字符串两种定义方式, 如果只是字符串方式的参数可以在第一个参数中定义, 例如:
- U('Article/cate',array('cate_id'=>1,'status'=>1))
- U('Article/cate','cate_id=1&status=1')
- U('Article/cate?cate_id=1&status=1')
三种方式是等效的, 都是生成 Article 控制器的 cate()操作 并且 cate_id 为 1 status 为 1 的 URL 地址
但是不允许使用下面的定义方式来传参数:
U('Article/cate/cate_id/1/status/1');
生成路由地址
U 方法还可以支持路由, 如果我们定义了一个路由规则为:
'blogs/:id\d'=>'Index/read'
那么可以使用
U('/blogs/1');
最终生成的 URL 地址是:
http://localhost:8999/index.php/Home/blogs/1
跳转和重定向
这应该是在开发中最常用的功能之一在应用开发中, 经常会遇到一些带有提示信息的跳转页面, 例如操作成功或者操作错误页面, 并且自动跳转到另外一个目标页面系统的 \ Think\Controller 类内置了两个跳转方法 success()和 error(), 用于页面跳转提示
跳转
使用方法很简单, 比如我们在 Index 控制器下新建一个方法 user(), 写上下面的内容:
- public function user()
- {
- $User = M('User');
- $data['username'] = 'Think';
- $data['email'] = 'Think@gmail.com';
- $result = $User->add($data);
- if($result){
- $this->success('success', '/Home/User/addUser');
- } else {
- $this->error('failed');
- }
- }
M('User')表示实例化一个 User 对象, add()方法是向数据库添加一条纪录然后我们需要新建一个 UserController, 在里面写上 addUser()方法
- <?php
- namespace Home\Controller;
- use Think\Controller;
- class UserController extends Controller {
- public function addUser()
- {
- echo 'add user done!';
- }
- }
然后在浏览器中访问 http://localhost:8999/Home/Index/user, 就可以看到 add user done! 了, 下面详细来说说这两个重定向方法
success()和 error()方法的第一个参数表示提示信息, 第二个参数表示跳转地址, 第三个参数是跳转时间(单位为秒), 例如:
- // redirect to /Article/index after 3 seconds when success
- $this->success('done','/Home/Article/index',3);
- // redirect to /Article/error after 5 seconds when failed
- $this->error('failed','/Home/Article/error',5);
如果不设置跳转时间, 默认的等待时间 success()方法是 1 秒, error()方法是 3 秒看到上面的两个跳转地址前面都带上了 / Home, 如果你想简写为 / Article/index, 你需要在 ThinkPHP 的入口文件 (项目目录下的 index.php) 中加上下面一行:
define('BIND_MODULE','Home');
而且这两个方法都有对应的模板, 默认的设置是两个方法对应的模板都是:
- 'TMPL_ACTION_ERROR' => THINK_PATH . 'Tpl/dispatch_jump.tpl',
- 'TMPL_ACTION_SUCCESS' => THINK_PATH . 'Tpl/dispatch_jump.tpl',
你可以根据自己的需要来修改模版
重定向
Controller 类的 redirect()方法可以实现页面的重定向功能
redirect()方法的参数用法和 U 函数的用法一致(参考上一部分 URL 生成部分), 例如:
$this->redirect('/Home/Article/show', array('id' => 2), 3, 'Redirecting...');
上面的用法是停留 3 秒后跳转到 Article 控制器的 show()操作, 并且显示页面跳转中字样 Redirecting..., 重定向后会改变当前的 URL 地址
为了成功进行测试, 我们在 IndexController 下添加 redirectToArticle()方法并写上上面那行代码:
- public function redirectToArticle()
- {
- $this->redirect('/Home/Article/show', array('id' => 2), 3, 'Redirecting...');
- }
然后我们创建一个 ArticleController, 并且为他添加 show()方法:
- namespace Home\Controller;
- use Think\Controller;
- class ArticleController extends Controller {
- public function show($id)
- {
- echo 'This is an Article Page';
- // $id 变量我们后续会用到, 现在只是演示跳转
- }
- }
然后在浏览器访问: http://localhost:8999/Home/Index/redirectToArticle, 等待三秒, 你就可以看到跳转之后的页面了
如果你仅仅是想重定向要一个指定的 URL 地址, 而不是到某个模块的操作方法, 可以直接使用 redirect()函数重定向, 例如
$this->redirect('/Home/Article/show/id/3', 'Redirecting...',3);
注: 控制器的 redirect()方法和 redirect()函数的区别在于前者是用 URL 规则定义跳转地址, 后者是一个纯粹的 URL 地址
注: 好像官方文档是这样写的
$this->redirect('/New/category/cate_id/2', 5, '页面跳转中...');
来源: https://www.php1.cn/detail/php-f8c1382030.html