ThinkPHP 跨控制器页面跳转 官方文档 未讲清楚

  摘要:在ThinkPHP学习过程中使用系统Controller类库提供的success()/error()跳转方法,官方《ThinkPHP3.2.3快速入门 》文档、《ThinkPHP3.2.3完全开发手册 》文档,都没有讲清楚跳转其它控制器/操作的原理,这里将从TP的源码讲解跳转过程,明确问题所在,以及怎样修正。

一 . 需要提前了解的东西

标签的href属性
  href 属性的值可以是任何有效文档的相对或绝对 URL,包括片段标识符和 JavaScript 代码段。如果用户选择了
标签中的内容,那么浏览器会尝试检索并显示 href 属性指定的 URL 所表示的文档,或者执行 JavaScript 表达式、方法和函数的列表。

  举例解释:

a标签href属性实例 说明
href=’http://www.baidu.com’ 点击后直接跳转至百度首页
href=’test.html’ 跳转至文档当前目录下test.html文件
href=’javascript:history.back(-1);’ 运行JS代码,返回上页
href=’ 返回操作前页面



  下面要讲到的TP的Controller类库的success/error方法其实是在模板中使用了第二种方法来跳转的。

二 . success/error方法问题所在、及修正

  先说问题出在哪里,当我在Index控制器里面希望跳转至Login控制器里面,按照官方文档的说法是这样做:
  $this->error(‘马上跳转!’,’Login/index’,1);
  可事实并不是这样
  URL会从
  http://localhost/ThinkPHP_Test/index.php/Home/Index/index
  跳转至
  http://localhost/ThinkPHP_Test/index.php/Home/Index/Login/index
  这显然不是我想要的,现将问题追踪的思路列举如下,并提出修正方法。

  上我自己的测试代码。

//IndexController.class.php

namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
    public function index(){
        $this->display();
    }
    public function click(){
        $this->error('马上跳转!','../Login/index',1);
        //$this->redirect('Login/index');
    }
}
?>
//这是模板文件Index/index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index indextitle>
head>
<body>
    <h1>Index indexh1>
    <a href="{:U('Index/click')}">跳转a>
    <br/>
    <a href="../Login/index">不用U的跳转a>
body>
html>
//LoginController.class.php

namespace Home\Controller;
use Think\Controller;

class LoginController extends Controller{
    public function index(){
        $this->display();
    }
}
?>
//这是模板文件Login/index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login indextitle>
head>
<body>
    <h1>Login indexh1>
body>
html>



下面来做说明:

1).TP的配置声明:

  • URL_MODEL是1,为PATHINFO模式;
  • 没有为Home模块做绑定;
  • PHP配置文件没有开启重写模块;
  • PHP的配置文件sites-enabled/000-default里面AllOverride None

2).运行TP

  http://localhost/ThinkPHP_Test/index.php/Home/Index/index

3).点击“跳转”链接

  当前页面源码里面可以查看到,这个“跳转”链接的href已经被ThinkPHP模板引擎替换为:
  /ThinkPHP_Test/index.php/Home/Index/click.html
  说明U()方法是将’Index/click’这样的字符串处理成了URL绝对地址,这样的访问是最安全的

4).Index控制器的click方法被调用

  执行跳转命令。
  官方文档是这样写的:
  $this->error(‘马上跳转!’,’Login/index’,1);
  下面我们用这种错误的用法来trace一下TP的源码,看看会出现什么问题

5).调用Think\Controller类库里面的error方法

  把error方法源码贴上:
  这里说明:success/error方法都调用这个dispatchJump,方法,不同的是success方法传入的$status参数为1,error方法传入的$status参数为0.

private function dispatchJump($message,$status=1,$jumpUrl='',$ajax=false) {
        if(true === $ajax || IS_AJAX) {// AJAX提交
            $data           =   is_array($ajax)?$ajax:array();
            $data['info']   =   $message;
            $data['status'] =   $status;
            $data['url']    =   $jumpUrl;
            $this->ajaxReturn($data);
        }
        if(is_int($ajax)) $this->assign('waitSecond',$ajax);
        if(!empty($jumpUrl)) $this->assign('jumpUrl',$jumpUrl);
        // 提示标题
        $this->assign('msgTitle',$status? L('_OPERATION_SUCCESS_') : L('_OPERATION_FAIL_'));
        //如果设置了关闭窗口,则提示完毕后自动关闭窗口
        if($this->get('closeWin'))    $this->assign('jumpUrl','javascript:window.close();');
        $this->assign('status',$status);   // 状态
        //保证输出不受静态缓存影响
        C('HTML_CACHE_ON',false);
        if($status) { //发送成功信息
            $this->assign('message',$message);// 提示信息
            // 成功操作后默认停留1秒
            if(!isset($this->waitSecond))    $this->assign('waitSecond','1');
            // 默认操作成功自动返回操作前页面
            if(!isset($this->jumpUrl)) $this->assign("jumpUrl",$_SERVER["HTTP_REFERER"]);
            $this->display(C('TMPL_ACTION_SUCCESS'));
        }else{
            $this->assign('error',$message);// 提示信息
            //发生错误时候默认停留3秒
            if(!isset($this->waitSecond))    $this->assign('waitSecond','3');
            // 默认发生错误的话自动返回上页
            if(!isset($this->jumpUrl)) $this->assign('jumpUrl',"javascript:history.back(-1);");
            $this->display(C('TMPL_ACTION_ERROR'));
            // 中止执行  避免出错后继续执行
            exit ;
        }
    }

  AJAX提交的方式我们不看。
  可以看到’Login/index’这个字符串是直接赋值给了$jumpUrl,可以看到在第10行赋值给模板了,名字也是jumpUrl。

6).再去看看TP的默认模板文件是怎么处理的

  这里只摘出关键代码:

页面自动 <a id="href" href="">跳转a>
等待时间: <b id="wait"> echo($waitSecond); ?>b>
<script type="text/javascript">
(function(){
var wait = document.getElementById('wait'),href = document.getElementById('href').href;
var interval = setInterval(function(){
    var time = --wait.innerHTML;
    if(time <= 0) {
        location.href = href;
        clearInterval(interval);
    };
}, 1000);
})();
script>

  ’Login/index’字符串直接赋值给href属性,在等待$waitSecond后,将页面定位到href属性值,这里出了问题,当把’Login/index’直接赋值给href属性的时候,浏览器会将现在的URL:
  http://localhost/ThinkPHP_Test/index.php/Home/Index/index
  跳转成:
  http://localhost/ThinkPHP_Test/index.php/Home/Index/Login/index
  这样就达不到我们的要求了



所以正确的做法是:
  在需要跳转的时候这么做:
  $this->error(‘马上跳转!’,’../Login/index’,1);
  相当于向上去一个目录,替换掉Index控制器,这样才能跳转成功。



<完>

你可能感兴趣的:(php)