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

来源:互联网 发布:七微南风知我意2微盘 编辑:程序博客网 时间:2024/06/08 08:17

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

一 . 需要提前了解的东西

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

  举例解释:

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



  下面要讲到的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<?phpnamespace 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<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Index index</title></head><body>    <h1>Index index</h1>    <a href="{:U('Index/click')}">跳转</a>    <br/>    <a href="../Login/index">不用U的跳转</a></body></html>
//LoginController.class.php<?phpnamespace Home\Controller;use Think\Controller;class LoginController extends Controller{    public function index(){        $this->display();    }}?>
//这是模板文件Login/index.html<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Login index</title></head><body>    <h1>Login index</h1></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="<?php echo($jumpUrl); ?>">跳转</a>等待时间: <b id="wait"><?php 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控制器,这样才能跳转成功。



<完>

1 0
原创粉丝点击