ThinkPHP控制器详解

在上一课程中,你可能会对ThinkPHP的路由会有一丝丝疑惑,不过没关系,学完本课程,很多事都会豁然开朗。

控制器文件命名遵守IndexController.class.php的方式

控制器的定义

在开始之前,我们还是需要明确一下控制器的定义:

<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {

  public function read($id){
    echo "read page with </br>" .$id;
  }

  public function top(){
    echo "top page </br>";
  }

}

如所见,前面在路由篇提到的控制器就是这么定义的:

使用相应的命名空间,默认是namespace Home\Controller
加载Think\Controller
新建控制器继承于Controller(或子类)
采用驼峰命名法,注意首字母大写
控制器内的公共方法可以看作一个操作,比如上面的read()和top()方法就可以看作操作,我们在路由篇的时候都验证过了。

http://localhost:8999/index.php/Home/Index/top
就是访问到top()方法,会在页面上打印出top page ,再次明确Home代表的是Home模块

有时候可能会遇到有和系统的关键字冲突的方法,这时候就可以使用设置操作方法后缀来解决了,具体请看官方文档:
http://document.thinkphp.cn/manual_3_2.html#define_controller

前置和后置操作

前置和后置操作指的是在执行某个操作方法之前和之后会自动调用的方法,不过仅对访问控制器有效,如在IndexController中为top()方法添加前置后置方法:

public function _before_top(){
    echo "before top page </br>";
  }
  public function top(){
    echo "top page </br>";
  }
  public function _after_top(){
    echo "after top page </br>";
  }

访问: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 </br>".$id;
  }

 public function archive($year, $month){
    echo "$year </br>".$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 </br>".$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 </br>".$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, '页面跳转中...');

以上所述就是本文的全部内容了,希望大家能够喜欢。

(0)

相关推荐

  • Thinkphp 空操作、空控制器、命名空间(详解)

    1.空操作 空操作是指系统在找不到请求的操作方法的时候,会定位到空操作(_empty)方法来执行,利用这个机制,我们可以实现错误页面和一些URL的优化. http://网址/index.php/Home/Main/login http://网址/index.php/Home/Main/hello 空操作 出现页面: 显示的错误信息过于详细,为安全以及优化页面起见,实行空操作 1.做一个_empty()方法.要在子类里面写,不要再父类里(推荐使用) function _empty() { echo

  • ThinkPHP空模块和空操作详解

    ThinkPHP的空模块和空操作也是很有实用意义的功能,空模块的概念就是当ThinkPHP找不到指定模块的时候,它会尝试去定位空模块(EmptyAction),执行空模块里面的index操作.同理,空操作也是同样的概念,当系统找不到指定模块下的操作方法的时候,就会尝试去定位空操作方法(empty).其实很好理解,就有点类似php虚拟主机里面的自定义404页面,但它比自定义404更加灵活,利用这个机制,我们可以实现错误页面和一些URL的优化,下面分别详细介绍下空模块和空操作的写法. 1.空模块,在

  • ThinkPHP控制器详解

    在上一课程中,你可能会对ThinkPHP的路由会有一丝丝疑惑,不过没关系,学完本课程,很多事都会豁然开朗. 控制器文件命名遵守IndexController.class.php的方式 控制器的定义 在开始之前,我们还是需要明确一下控制器的定义: <?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function read($id){ ec

  • ThinkPHP函数详解之M方法和R方法

    首先给大家介绍ThinkPHP函数详解:M方法 M方法用于实例化一个基础模型类,和D方法的区别在于: 1.不需要自定义模型类,减少IO加载,性能较好: 2.实例化后只能调用基础模型类(默认是Model类)中的方法: 3.可以在实例化的时候指定表前缀.数据库和数据库的连接信息: D方法的强大则体现在你封装的自定义模型类有多强,不过随着新版ThinkPHP框架的基础模型类的功能越来越强大,M方法也比D方法越来越实用了. M方法的调用格式: M('[基础模型名:]模型名','数据表前缀','数据库连接

  • ThinkPHP路由详解

    有了基本配置,我们就可以来访问我们的应用默认首页了.进入到项目目录,可以直接使用PHP内置服务器来开始访问,比如: php -S localhost:8999 浏览器输入localhost:8999就可以看到ThinkPHP的默认首页了:一个笑脸. 在这里,我们访问到的是ThinkPHP自带的默认入口文件index.php也就是访问到的是IndexController的index()方法,这是因为ThinkPHP默认设置: 'DEFAULT_CONTROLLER' => 'Index' 如果你查

  • ThinkPHP模型详解

    模型定义,默认情况下,ThinkPHP的模型类是位于/Home/Model/目录之下,模型类通常需要继承系统的\Think\Model类或其子类,下面是一个Home\Model\UserModel类的定义: 文件命名遵守UserModel.class.php的方式,跟控制器的命名一样 <?php namespace Home\Model; use Think\Model; class UserModel extends Model { } 模型类的作用大多数情况是操作数据表的,如果按照系统的规范

  • AngularJS控制器详解及示例代码

    AngularJS应用主要依赖于控制器来控制数据在应用程序中的流动.控制器采用ng-controller指令定义.控制器是一个包含属性/属性和JavaScript对象的功能.每个控制器接受$scope参数指定应用程序/模块,由控制器控制. <div ng-app="" ng-controller="studentController"> ... </div> 在这里,我们已经声明采用ng-controller指令的控制器studentCont

  • AngularJS入门教程之控制器详解

    AngularJS 控制器 AngularJS 控制器 控制 AngularJS 应用程序的数据. AngularJS 控制器是常规的 JavaScript 对象. AngularJS 控制器 AngularJS 应用程序被控制器控制. ng-controller 指令定义了应用程序控制器. 控制器是 JavaScript 对象,由标准的 JavaScript 对象的构造函数 创建. AngularJS 实例 <!DOCTYPE html> <html> <head>

  • Angular企业级开发——MVC之控制器详解

    1.MVC中的控制器 AngularJS的控制器主要为了把模型和视图连接在一起.大多数业务逻辑操作都会放在视图对应的控制器中.当然如果我们能够把业务逻辑放到后端的REST服务中,就可以开发轻量级AngularJS应用. 涉及到多个控制器中使用的业务逻辑,需要放到一个公共的服务中,然后把改服务注入使用到该业务逻辑的控制器中. 2.理解控制器 在AngularJS的控制器中,构造函数会有$scope参数.当一个控制器通过ng-controller指令连接到DOM上,Angular将实例化一个新的控制

  • thinkphp中的多表关联查询的实例详解

    thinkphp中的多表关联查询的实例详解 在进行后端管理系统的编程的时候一般会使用框架来进行页面的快速搭建,我最近使用比较多的就是thinkphp框架,thinkphp框架的应用其实就是把前端和后端进行分割管理,前端用户登录查询系统放在thinkphp中的home文件夹中进行管理,后端管理系统放在thinkphp中的admin文件夹中进行管理.对了,在使用thinkphp框架的时候是是要用到mvc架构的,mvc架构就是model(数据模型).view(视图).controller(控制器)的结

  • thinkPHP中钩子的两种配置调用方法详解

    本文实例讲述了thinkPHP中钩子的两种配置调用方法.分享给大家供大家参考,具体如下: thinkphp的钩子行为类是一个比较难以理解的问题,网上有很多写thinkphp钩子类的文章,我也是根据网上的文章来设置thinkphp的钩子行为的,但根据这些网上的文章,我在设置的过程中,尝试了十几次都没有成功,不过,我还是没有放弃,最后还是在一边调节细节,一边试验的过程中实现了钩子行为的设置.下面是我个人的设置经验,在这里跟大家分享一下. 个人做了两种设置,都试验成功了,一个简单点,在thinkphp

随机推荐