企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
#定义 接下来要讲的是控制器,MVC中的C。 一般来说,ThinkPHP的控制器是一个类,而操作则是控制器类的一个公共方法。 下面就是一个典型的控制器类的定义: ~~~ <?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function hello(){ echo 'hello,thinkphp!'; } } ~~~ `Home\IndexController`类就代表了Home模块下的Index控制器,而hello操作就是`Home\IndexController`类的hello(公共)方法。 当访问 `http://serverName/index.php/Home/Index/hello` 后会输出: hello,thinkphp! 控制器通常需要继承系统的Controller类或者其子类 控制器的名称采用驼峰法命名(首字母大写),控制器文件位于 `Home/Controller/IndexController.class.php`。 `IndexController`控制器类的hello方法就是操作方法,访问下面的URL地址: `http://serverName/Home/Index/hello` 会输出 hello 操作方法的定义必须是公共方法,否则会报操作错误 ##实例化控制器 访问控制器的实例化通常是自动完成的,系统会根据URL地址解析出访问的控制器名称自动实例化,并且调用相关的操作方法。 如果你需要跨控制器调用的话,则可以单独实例化: // 实例化Home模块的User控制器 $User = new \Home\Controller\UserController(); // 实例化Admin模块的Blog控制器 $Blog = new \Admin\Controller\BlogController(); 系统为上面的控制器实例化提供了一个快捷调用方法A,上面的代码可以简化为: // 假设当前模块是Home模块 $User = A('User'); $Blog = A('Admin/Blog'); 默认情况下,A方法实例化的是默认控制器层(Controller),如果你要实例化其他的分层控制器的话,可以使用: // 假设当前模块是Home模块 // 实例化Event控制器 $User = A('User','Event'); $Blog = A('Admin/Blog','Event'); 上面的代码等效于: // 实例化Home模块的User事件控制器 $User = new \Home\Event\UserEvent(); // 实例化Admin模块的Blog事件控制器 $Blog = new \Admin\Event\BlogEvent(); # 影响控制器方法进入的因素 ## 伪静态 URL伪静态通常是为了满足更好的SEO效果,ThinkPHP支持伪静态URL设置,可以通过设置`URL_HTML_SUFFIX`参数随意在URL的最后增加你想要的静态后缀,而不会影响当前操作的正常执行。例如,我们设置 'URL_HTML_SUFFIX'=>'shtml' 的话,我们可以把下面的URL http://serverName/Home/Blog/read/id/1 变成 http://serverName/Home/Blog/read/id/1.shtml 后者更具有静态页面的URL特征,但是具有和前面的URL相同的执行效果,并且不会影响原来参数的使用。 默认情况下,伪静态的设置为_html_, 如果我们设置伪静态后缀为空 'URL_HTML_SUFFIX'=>'' 则可以支持所有的静态后缀,并且会记录当前的伪静态后缀到常量 __EXT__ ,但不会影响正常的页面访问。 例如: ~~~ http://serverName/Home/blog/3.html http://serverName/Home/blog/3.shtml http://serverName/Home/blog/3.xml http://serverName/Home/blog/3.pdf ~~~ 都可以正常访问,如果要获取当前的伪静态后缀,通过常量 __EXT__ 获取即可。 如果希望支持多个伪静态后缀,可以直接设置如下: ~~~ // 多个伪静态后缀设置 用|分割 'URL_HTML_SUFFIX' => 'html|shtml|xml' ~~~ 那么,当访问 `http://serverName/Home/blog/3.pdf` 的时候会报系统错误。 可以设置禁止访问的URL后缀,例如: ~~~ 'URL_DENY_SUFFIX' => 'pdf|ico|png|gif|jpg', // URL禁止访问的后缀设置 ~~~ 如果访问 `http://serverName/Home/blog/3.pdf` 就会直接返回404错误。 > 注意: >`URL_DENY_SUFFIX`的优先级比`URL_HTML_SUFFIX`要高。 另外 >伪静态和静态页面缓存是两个不一样的概念 ## URL大小写 系统默认的规范是根据URL里面的模块名、控制器名来定位到具体的控制器类的,从而执行控制器类的操作方法。 以URL访问 `http://serverName/index.php/Home/Index/index` 为例,其实访问的控制器类文件是: `Application/Home/Controller/IndexController.class.php` 如果是Windows环境,无论大小写如何都能定位到`IndexController.class.php`文件,所以下面的访问都是有效的: ~~~ http://serverName/index.php/Home/Index/index http://serverName/index.php/Home/index/index http://serverName/index.php/home/index/Index ~~~ 如果在Linux环境下面,一旦大小写不一致,就会发生URL里面使用小写模块名不能找到模块类的情况。例如在Linux环境下面,我们访问 `http://serverName/index.php/home/index/index` 其实请求的控制器文件是 `Application/home/Controller/indexController.class.php` 因为,我们定义的控制器类是IndexController而不是indexController(参考ThinkPHP的命名规范),由于Linux的文件特性,其实是不存在indexController控制器文件的,就会出现Index控制器不存在的错误,这样的问题会造成用户体验的下降。 但是系统本身提供了一个不区分URL大小写的解决方案,可以通过配置简单实现。 只要在项目配置中,增加: `'URL_CASE_INSENSITIVE' =>true` 配置好后,即使是在Linux环境下面,也可以实现URL访问不再区分大小写了。 ~~~ http://serverName/index.php/Home/Index/index // 将等效于 http://serverName/index.php/home/index/index ~~~ 这里需要注意一个地方,一旦开启了不区分URL大小写后,如果我们要访问类似UserTypeController的控制器,那么正确的URL访问应该是: ~~~ // 正确的访问地址 http://serverName/index.php/home/user_type/index // 错误的访问地址(linux环境下) http://serverName/index.php/home/usertype/index ~~~ 利用系统提供的U方法可以为你自动生成相关的URL地址。 如果设置 ~~~ 'URL_CASE_INSENSITIVE' =>false ~~~ 的话,URL就又变成: `http://serverName/index.php/Home/UserType/add` > 注意:URL不区分大小写并不会改变系统的命名规范,并且只有按照系统的命名规范后才能正确的实现URL不区分大小写。 ### 如何知道是URL大小写导致的问题呢? 首先,我们url错误了访问会报错,即使没开调试模式,日志里也会记录报错。 然后,当遇到“Windows下开发的应用部署到服务器上,就访问不了”,首先我们要排除的可能原因就是大小写问题了。 最后,为了保证我们写的代码具有良好的可移植性。开发过程中,建议我们关闭 `URL_CASE_INSENSITIVE` 这个配置。 ## 路由 这个会在进阶知识中讲,大家只需要知道路由会影响访问的控制器操作(执行谁?、是否带隐形参数) # 流程相关 ## 前置与后置操作 前置和后置操作指的是在执行某个操作方法之前和之后会自动调用的方法,不过仅对访问控制器有效。 > 其他的分层控制器层和内部调用控制器的情况下前置和后置操作是无效的。 系统会检测当前操作是否具有前置和后置操作,如果存在就会按照顺序执行,前置和后置操作的定义方式如下: ~~~ <?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller{ //前置操作方法 public function _before_index(){ echo 'before<br/>'; } public function index(){ echo 'index<br/>'; } //后置操作方法 public function _after_index(){ echo 'after<br/>'; } } ~~~ 如果我们访问 `http://serverName/index.php/Home/Index/index` 结果会输出 ~~~ before index after ~~~ >前置和后置操作的注意事项如下: >1. 如果当前的操作并没有定义操作方法,而是直接渲染模板文件,那么如果定义了前置和后置方法的话,依然会生效。真正有模板输出的可能仅仅是当前的操作,前置和后置操作一般情况是没有任何输出的。 >2. 需要注意的是,在有些方法里面使用了exit或者错误输出之类的话 有可能不会再执行后置方法了。例如,如果在当前操作里面调用了系统Action的error方法,那么将不会再执行后置操作,但是不影响success方法的后置方法执行。 ## 输入变量 在Web开发过程中,我们经常需要获取系统变量或者用户提交的数据,这些变量数据错综复杂,而且一不小心就容易引起安全隐患,但是如果利用好ThinkPHP提供的变量获取功能,就可以轻松的获取和驾驭变量了。 ### 获取变量 虽然你仍然可以在开发过程中使用传统方式获取各种系统变量,例如 ~~~ $id = $_GET['id']; // 获取get变量 $name = $_POST['name']; // 获取post变量 $value = $_SESSION['var']; // 获取session变量 $name = $_COOKIE['name']; // 获取cookie变量 $file = $_SERVER['PHP_SELF']; // 获取server变量 ~~~ 但是我们不建议直接使用传统方式获取,因为没有统一的安全处理机制,后期如果调整的话,改起来会比较麻烦。所以,更好的方式是在框架中统一使用I函数进行变量获取和过滤。 I方法是ThinkPHP用于更加方便和安全的获取系统输入变量,可以用于任何地方,用法格式如下: **I('变量类型.变量名/修饰符',['默认值'],['过滤方法'],['额外数据源'])** 变量类型是指请求方式或者输入类型,包括: |变量类型|含义| ||| | get |获取GET参数| |post|获取POST参数| |param |自动判断请求类型获取GET、POST或者PUT参数| |request|获取REQUEST 参数| |put |获取PUT 参数| |session|获取 $_SESSION 参数| |cookie |获取 $_COOKIE 参数| |server |获取 $_SERVER 参数| |globals|获取 $GLOBALS参数| |path|获取 PATHINFO模式的URL参数(3.2.2新增)| |data|获取 其他类型的参数,需要配合额外数据源参数(3.2.2新增)| >注意:变量类型不区分大小写。 >变量名则严格区分大小写。 >默认值和过滤方法均属于可选参数。 >变量修饰符是3.2.3版本新增 我们以GET变量类型为例,说明下I方法的使用: ~~~ echo I('get.id'); // 相当于 $_GET['id'] echo I('get.name'); // 相当于 $_GET['name'] ~~~ 支持默认值: ~~~ echo I('get.id',0); // 如果不存在$_GET['id'] 则返回0 echo I('get.name',''); // 如果不存在$_GET['name'] 则返回空字符串 ~~~ 采用方法过滤: ~~~ // 采用htmlspecialchars方法对$_GET['name'] 进行过滤,如果不存在则返回空字符串 echo I('get.name','','htmlspecialchars'); ~~~ 支持直接获取整个变量类型,例如: ~~~ // 获取整个$_GET 数组 I('get.'); ~~~ 用同样的方式,我们可以获取post或者其他输入类型的变量,例如: ~~~ I('post.name','','htmlspecialchars'); // 采用htmlspecialchars方法对$_POST['name'] 进行过滤,如果不存在则返回空字符串 I('session.user_id',0); // 获取$_SESSION['user_id'] 如果不存在则默认为0 I('cookie.'); // 获取整个 $_COOKIE 数组 I('server.REQUEST_METHOD'); // 获取 $_SERVER['REQUEST_METHOD'] ~~~ param变量类型是框架特有的支持自动判断当前请求类型的变量获取方式,例如: echo I('param.id'); //相当于 I('request.id') 由于param类型是I函数默认获取的变量类型,因此事实上param变量类型的写法可以简化为: I('id'); // 等同于 I('param.id') I('name'); // 等同于 I('param.name') 3.2.2新增了`path和data两个变量类型`,用法如下: path类型变量可以用于获取URL参数(必须是PATHINFO模式参数有效,无论是GET还是POST方式都有效),例如: 当前访问URL地址是 `http://serverName/index.php/New/2013/06/01` 那么我们可以通过 ~~~ echo I('path.1'); // 输出2013 echo I('path.2'); // 输出06 echo I('path.3'); // 输出01 ~~~ data类型变量可以用于获取不支持的变量类型的读取,例如: I('data.file1','','',$_FILES); ### 变量过滤 如果你没有在调用I函数的时候指定过滤方法的话,系统会采用默认的过滤机制(由DEFAULT_FILTER配置),事实上,该参数的默认设置是: ~~~ // 系统默认的变量过滤机制 'DEFAULT_FILTER' => 'htmlspecialchars' ~~~ 也就说,I方法的所有获取变量如果没有设置过滤方法的话都会进行`htmlspecialchars`过滤,那么: ~~~ // 等同于 htmlspecialchars($_GET['name']) I('get.name'); ~~~ 同样,该参数也可以设置支持多个过滤,例如: `'DEFAULT_FILTER'=> 'strip_tags,htmlspecialchars'` 设置后,我们在使用: ~~~ // 等同于 htmlspecialchars(strip_tags($_GET['name'])) I('get.name'); ~~~ 如果我们在使用I方法的时候 指定了过滤方法,那么就会忽略DEFAULT_FILTER的设置,例如: ~~~ // 等同于 strip_tags($_GET['name']) echo I('get.name','','strip_tags'); ~~~ I方法的第三个参数如果传入函数名,则表示调用该函数对变量进行过滤并返回(在变量是数组的情况下自动使用array_map进行过滤处理),否则会调用PHP内置的`filter_var`方法进行过滤处理,例如: ~~~ I('post.email','',FILTER_VALIDATE_EMAIL); ~~~ 表示 会对`$_POST['email']` 进行 格式验证,如果不符合要求的话,返回空字符串。 (关于更多的验证格式,可以参考 官方手册的filter_var用法。) 或者可以用下面的字符标识方式: `I('post.email','','email');` 可以支持的过滤名称必须是`filter_list`方法中的有效值(不同的服务器环境可能有所不同),可能支持的包括 ~~~ int boolean float validate_regexp validate_url validate_email validate_ip string stripped encoded special_chars unsafe_raw email url number_int number_float magic_quotes callback ~~~ 3.2.3版本开始支持进行正则匹配过滤,例如: ~~~ // 采用正则表达式进行变量过滤 I('get.name','','/^[A-Za-z]+$/'); I('get.id',0,'/^\d+$/'); ~~~ 如果正则匹配不通过的话,则返回默认值。 在有些特殊的情况下,我们不希望进行任何过滤,即使DEFAULT_FILTER已经有所设置,可以使用 ~~~ // 下面两种方式都不采用任何过滤方法 I('get.name','',''); I('get.id','',false); ~~~ 一旦过滤参数设置为空字符串或者false,即表示不再进行任何的过滤。 ### 变量修饰符 3.2.3版本开始,I函数支持对变量使用修饰符功能,可以更好的过滤变量。 用法如下: **I('变量类型.变量名/修饰符')**; 例如: ~~~ I('get.id/d'); I('post.name/s'); I('post.ids/a'); ~~~ 可以使用的修饰符包括: |修饰符 |作用| ||| |s |强制转换为字符串类型| |d |强制转换为整形类型| |b |强制转换为布尔类型| |a |强制转换为数组类型| |f |强制转换为浮点类型| ## 请求类型 在很多情况下面,我们需要判断当前操作的请求类型是GET 、POST 、PUT或 DELETE,一方面可以针对请求类型作出不同的逻辑处理,另外一方面有些情况下面需要验证安全性,过滤不安全的请求。 系统内置了一些**常量**用于判断请求类型,包括: |常量|说明| ||| |IS_GET|判断是否是GET方式提交| |IS_POST|判断是否是POST方式提交| |IS_PUT|判断是否是PUT方式提交| |IS_DELETE|判断是否是DELETE方式提交| |IS_AJAX|判断是否是AJAX提交| |REQUEST_METHOD|当前提交类型| 使用举例如下: ~~~ class UserController extends Controller{ public function update(){ if (IS_POST){ $User = M('User'); $User->create(); $User->save(); $this->success('保存完成'); }else{ $this->error('非法请求'); } } } ~~~ > 需要注意的是,如果使用的是ThinkAjax或者自己写的Ajax类库的话,需要在表单里面添加一个隐藏域,告诉后台属于ajax方式提交,默认的隐藏域名称是ajax(可以通过VAR_AJAX_SUBMIT配置),如果是JQUERY类库的话,则无需添加任何隐藏域即可自动判断。 ## 空操作 空操作是指系统在找不到请求的操作方法的时候,会定位到空操作(`_empty`)方法来执行,利用这个机制,我们可以实现错误页面和一些URL的优化。 例如,下面我们用空操作功能来实现一个城市切换的功能。 我们只需要给CityController类定义一个`_empty`(空操作)方法: ~~~ <?php namespace Home\Controller; use Think\Controller; class CityController extends Controller{ public function _empty($name){ //把所有城市的操作解析到city方法 $this->city($name); } //注意 city方法 本身是 protected 方法 protected function city($name){ //和$name这个城市相关的处理 echo '当前城市' . $name; } } ~~~ 接下来,我们就可以在浏览器里面输入 http://serverName/index.php/Home/City/beijing/ http://serverName/index.php/Home/City/shanghai/ http://serverName/index.php/Home/City/shenzhen/ 由于City控制器并没有定义beijing、shanghai或者shenzhen操作方法,因此系统会定位到空操作方法 `_empty`中去解析,`_empty`方法的参数就是当前URL里面的操作名,因此会看到依次输出的结果是: ~~~ 当前城市:beijing 当前城市:shanghai 当前城市:shenzhen ~~~ > 注意:空操作方法仅在你的控制器类继承系统的Think\Controller类才有效,否则需要自己定义 __call 来实现。 这个空操作的应用场景有哪些呢? - 错误处理 - 单页处理(比如企业单页-关于我们之类的实现) - 一些接口动态方法的处理,如微博、微信 - 缩短url ## 空控制器 空控制器的概念是指当系统找不到请求的控制器名称的时候,系统会尝试定位空控制器(EmptyController),利用这个机制我们可以用来定制错误页面和进行URL的优化。 现在我们把前面的需求进一步,把URL由原来的 `http://serverName/index.php/Home/City/shanghai/` 变成 `http://serverName/index.php/Home/shanghai/` 这样更加简单的方式,如果按照传统的模式,我们必须给每个城市定义一个控制器类,然后在每个控制器类的index方法里面进行处理。可是如果使用空控制器功能,这个问题就可以迎刃而解了。 我们可以给项目定义一个EmptyController类 ~~~ <?php namespace Home\Controller; use Think\Controller; class EmptyController extends Controller{ public function index(){ //根据当前控制器名来判断要执行那个城市的操作 $cityName = CONTROLLER_NAME; $this->city($cityName); } //注意 city方法 本身是 protected 方法 protected function city($name){ //和$name这个城市相关的处理 echo '当前城市' . $name; } } ~~~ 接下来,我们就可以在浏览器里面输入 ~~~ http://serverName/index.php/Home/beijing/ http://serverName/index.php/Home/shanghai/ http://serverName/index.php/Home/shenzhen/ ~~~ 由于系统并不存在beijing、shanghai或者shenzhen控制器,因此会定位到空控制器(EmptyController)去执行,会看到依次输出的结果是: ~~~ 当前城市:beijing 当前城市:shanghai 当前城市:shenzhen ~~~ > 空控制器和空操作还可以同时使用,用以完成更加复杂的操作。 # 控制器相关的输出 ## URL生成 为了配合所使用的URL模式,我们需要能够动态的根据当前的URL设置生成对应的URL地址,为此,ThinkPHP内置提供了U方法,用于URL的动态生成,可以确保项目在移植过程中不受环境的影响。 ### 定义规则 U方法的定义规则如下(方括号内参数根据实际应用决定): **U('地址表达式',['参数'],['伪静态后缀'],['显示域名'])** #### 地址表达式 地址表达式的格式定义如下: ~~~ [模块/控制器/操作#锚点@域名]?参数1=值1&参数2=值2... ~~~ 如果不定义模块的话 就表示当前模块名称,下面是一些简单的例子: ~~~ U('User/add') // 生成User控制器的add操作的URL地址 U('Blog/read?id=1') // 生成Blog控制器的read操作 并且id为1的URL地址 U('Admin/User/select') // 生成Admin模块的User控制器的select操作的URL地址 ~~~ #### 参数 U方法的第二个参数支持数组和字符串两种定义方式,如果只是字符串方式的参数可以在第一个参数中定义,例如: ~~~ U('Blog/cate',array('cate_id'=>1,'status'=>1)) U('Blog/cate','cate_id=1&status=1') U('Blog/cate?cate_id=1&status=1') ~~~ 三种方式是等效的,都是生成Blog控制器的cate操作 并且`cate_id`为1 `status`为1的URL地址。 但是不允许使用下面的定义方式来传参数 `U('Blog/cate/cate_id/1/status/1');` #### 伪静态后缀 U函数会自动识别当前配置的伪静态后缀,如果你需要指定后缀生成URL地址的话,可以显式传入,例如: `U('Blog/cate','cate_id=1&status=1','xml');` ### 自动识别 根据项目的不同URL设置,同样的U方法调用可以智能地对应产生不同的URL地址效果,例如针对: `U('Blog/read?id=1');` 这个定义为例。 如果当前URL设置为普通模式的话,最后生成的URL地址是: `http://serverName/index.php?m=Blog&a=read&id=1` 如果当前URL设置为PATHINFO模式的话,同样的方法最后生成的URL地址是: `http://serverName/index.php/Home/Blog/read/id/1` 如果当前URL设置为REWRITE模式的话,同样的方法最后生成的URL地址是: ~~~ http://serverName/Home/Blog/read/id/1 ~~~ 如果当前URL设置为REWRITE模式,并且设置了伪静态后缀为.html的话,同样的方法最后生成的URL地址是: `http://serverName/Home/Blog/read/id/1.html` > 如果开启了`URL_CASE_INSENSITIVE`,则会统一生成小写的URL地址。 ### 生成路由地址 U方法还可以支持路由,如果我们定义了一个路由规则为: `'news/:id\d'=>'News/read'` 那么可以使用 `U('/news/1');` 最终生成的URL地址是: `http://serverName/index.php/Home/news/1` > 注意:如果你是在模板文件中直接使用U方法的话,需要采用 {:U('参数1', '参数2'…)} 的方式,具体参考模板的使用函数内容。 ### 域名支持 如果你的应用涉及到多个子域名的操作地址,那么也可以在U方法里面指定需要生成地址的域名,例如: `U('Blog/read@blog.thinkphp.cn','id=1');` @后面传入需要指定的域名即可。 系统会自动判断当前是否SSL协议,生成`https://`。 此外,U方法的第4个参数如果设置为true,表示自动识别当前的域名,并且会自动根据子域名部署设置`APP_SUB_DOMAIN_DEPLOY`和`APP_SUB_DOMAIN_RULES`自动匹配生成当前地址的子域名。 ### 锚点支持 U函数可以直接生成URL地址中的锚点,例如: ~~~ U('Blog/read#comment?id=1'); ~~~ 生成的URL地址可能是: `http://serverName/index.php/Home/Blog/read/id/1#comment` ## AJAX返回 ThinkPHP可以很好的支持AJAX请求,系统的`\Think\Controller`类提供了`ajaxReturn`方法用于AJAX调用后返回数据给客户端。并且支持JSON、JSONP、XML和EVAL四种方式给客户端接受数据,并且支持配置其他方式的数据格式返回。 ajaxReturn方法调用示例: ~~~ $data = 'ok'; $this->ajaxReturn($data); ~~~ 支持返回数组数据: ~~~ $data['status'] = 1; $data['content'] = 'content'; $this->ajaxReturn($data); ~~~ 默认配置采用JSON格式返回数据(通过配置DEFAULT_AJAX_RETURN进行设置),我们可以指定格式返回,例如: ~~~ // 指定XML格式返回数据 $data['status'] = 1; $data['content'] = 'content'; $this->ajaxReturn($data,'xml'); ~~~ 返回数据data可以支持字符串、数字和数组、对象,返回客户端的时候根据不同的返回格式进行编码后传输。如果是JSON/JSONP格式,会自动编码成JSON字符串,如果是XML方式,会自动编码成XML字符串,如果是EVAL方式的话,只会输出字符串data数据。 > JSON和JSONP虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种非官方跨域数据交互协议。一个是描述信息的格式,一个是信息传递的约定方法。 默认的JSONP格式返回的处理方法是`jsonpReturn`,如果你采用不同的方法,可以设置: ~~~ 'DEFAULT_JSONP_HANDLER' => 'myJsonpReturn', // 默认JSONP格式返回的处理方法 ~~~ 或者直接在页面中用callback参数来指定。 > 除了上面四种返回类型外,我们还可以通过行为扩展来增加其他类型的支持,只需要对`ajax_return`标签位进行行为绑定即可。 ## 跳转和重定向 ### 页面跳转 在应用开发中,经常会遇到一些带有提示信息的跳转页面,例如操作成功或者操作错误页面,并且自动跳转到另外一个目标页面。系统的`\Think\Controller`类内置了两个跳转方法success和error,用于页面跳转提示,而且可以支持ajax提交。 使用方法很简单,举例如下: ~~~ $User = M('User'); //实例化User对象 $result = $User->add($data); if($result){ //设置成功后跳转页面的地址,默认的返回页面是$_SERVER['HTTP_REFERER'] $this->success('新增成功', 'User/list'); } else { //错误页面的默认跳转页面是返回前一页,通常不需要设置 $this->error('新增失败'); } ~~~ success和error方法的第一个参数表示提示信息,第二个参数表示跳转地址,第三个参数是跳转时间(单位为秒),例如: ~~~ // 操作完成3秒后跳转到 /Article/index $this->success('操作完成','/Article/index',3); // 操作失败5秒后跳转到 /Article/error $this->error('操作失败','/Article/error',5); ~~~ 跳转地址是可选的,success方法的默认跳转地址是`$_SERVER["HTTP_REFERER"]`,error方法的默认跳转地址是`javascript:history.back(-1);`。 > 默认的等待时间success方法是1秒,error方法是3秒 `success`和`error`方法都可以对应的模板,默认的设置是两个方法对应的模板都是: ~~~ //默认错误跳转对应的模板文件 'TMPL_ACTION_ERROR' => THINK_PATH . 'Tpl/dispatch_jump.tpl', //默认成功跳转对应的模板文件 'TMPL_ACTION_SUCCESS' => THINK_PATH . 'Tpl/dispatch_jump.tpl', ~~~ 也可以使用项目内部的模板文件 ~~~ //默认错误跳转对应的模板文件 'TMPL_ACTION_ERROR' => 'Public:error'; //默认成功跳转对应的模板文件 'TMPL_ACTION_SUCCESS' => 'Public:success'; ~~~ 模板文件可以使用模板标签,并且可以使用下面的模板变量: | 变量 | 含义 | |-----|-----| | $msgTitle | 操作标题 | | $message | 页面提示信息 | | $status | 操作状态 1表示成功 0 表示失败 具体还可以由项目本身定义规则 | | $waitSecond | 跳转等待时间 单位为秒 | | $jumpUrl | 跳转页面地址 | success和error方法会自动判断当前请求是否属于Ajax请求,如果属于Ajax请求则会调用ajaxReturn方法返回信息。 ajax方式下面,success和error方法会封装下面的数据返回: ~~~ $data['info'] = $message; // 提示信息内容 $data['status'] = $status; // 状态 如果是success是1 error 是0 $data['url'] = $jumpUrl; // 成功或者错误的跳转地址 ~~~ ### 重定向 Controller类的redirect方法可以实现页面的重定向功能。 redirect方法的参数用法和U函数的用法一致(参考[URL生成](1718)部分),例如: ~~~ //重定向到New模块的Category操作 $this->redirect('New/category', array('cate_id' => 2), 5, '页面跳转中...'); ~~~ 上面的用法是停留5秒后跳转到New模块的category操作,并且显示页面跳转中字样,重定向后会改变当前的URL地址。 如果你仅仅是想重定向要一个指定的URL地址,而不是到某个模块的操作方法,可以直接使用`redirect`函数重定向,例如: ~~~ //重定向到指定的URL地址 redirect('/New/category/cate_id/2', 5, '页面跳转中...') ~~~ Redirect函数的第一个参数是一个URL地址。 > 控制器的redirect方法和redirect函数的区别在于前者是用URL规则定义跳转地址,后者是一个纯粹的URL地址。 # 自行充电的可选项 ## 插件控制器 ## 操作绑定到类 # 总结 通过本章节,你应该能解决以下问题: - 如何定义一个控制器 - 如何在控制器中引用任意控制器 - 知道有哪些因素会限制你访问某控制器的某方法 - 知道如何控制控制器方法中的流程 - 知道如何生成你想要的URL - 知道使用路由或空控制器和空操作来动态处理url - 知道输出模板或者你想要的格式如Json、或重定向