YII本身的跳转很灵活。一般的MVC出现跳转的也不外乎:
     
     (1)V->V   页面之前的跳转
    
(2)C->V 正常的MVC方式
(3)V->C 请求数据接口数据传参,我还是一般都会用JS的ajax实现
这三种也都逃不了YII特有的方法和PHP原生的方法实现
首先针对于v->v这种页面直接跳转的方式,最常见的就是超链接。
超链接在原生的写法中是直接写绝对地址或ur拼接。这种在YII中由于跳转基本是通过controller从中实现的,这边要注意其实这里还是和v->c类似,url拼接的还是相应规则的内容(否则很多有YII引入的样式表和JS都无法正常表现)
原生写法
<a href='index.php/index?data="abc" ' >YII写法
<a href="<?= URL::to('index','date'=>'abc') ?>" >
或更直接的PHP风格
<?=HTML::a('index','date'=>'abc') ?>看的出来这里的URL就是C层转向V的地址,所以我们的V->C层代码也不外乎这样
再来看下c->v
这一步可以说是MVC的最经典的操作,一般其他框架比较常见的是SMARTY传至并访问。这里我们要用的是YII的redner系列方法。例如最常用的
$this->render('index',[参数列表])另外如果实现返回上一个页面的效果可以使用:
     
      Yii::$app->request->referrer
     
     或者
     
      Yii::$app->request->getReferre()
     
     这里有几个tips:
     
     1.对于render其实底层实现的就是renderContent。只是将页面的中间部分放入,包含YII的头部和底部,这里如果需要修改可以换位rendiect
    
2.在跳转的时候默认的是本控制器,如果需要其他控制器可以在前面多加一个“/”.比如我是通过DefaultController.php的index方法跳转当前页,如果我要去LoginController处理登录业务的页面,我就需要“//login/login”
简单整理:
在yii2中,引入视图模版文件的4种方法的区别如下:
     1)、“@app” 开头,“@app”是一个路径别名,对应站点根目录。比如项目路径为:E:/www/yii2/,引入为:$this->render(‘@app/views/site/about.php’),则对应的文件所在磁盘路径为:“E:/www/yii2
     
      /views/site/about.php”(可以用var_dump(Yii::getAlias(‘
      
       @app
      
      ‘));查看@app的值)。
     
    
     
      2)、默认为控制器或小部件对应默认的路径,例如:SiteController.php中return $this->render(“about”) 对应到  @app/views/site/about.php (即:E:/www/yii2/views/site/about.php)。
     
    
     
      3)、“//” 开头对应的视图文件路径为 @app/views/… ,例如 //site/about 对应到 @app/views/site/about.php 。
     
    
     
      4)、“/”开头表示相对于当前views目录的位置,例如:如果当前模块为user,/site/about对应成@app/modules/user/views/site/about.php , 如果不是模块,/site/about对应 @app/views/site/about.php 。注意:“//”和“/”的区别在于,“//”相当于绝对路径,“/”相当于相对路径。具体对比如下:
     
    
| 控制器 | $this->render | 模版路径 | 
| E:/yii2/controllers/SiteController.php | //site/about | E:/yii2/views/site/about.php | 
| E:/yii2/modules/user/controllers/SiteController.php | //site/about | E:/yii2/views/site/about.php | 
| E:/yii2/controllers/SiteController.php | /site/about | E:/yii2/views/site/about.php | 
| E:/yii2/modules/user/controllers/SiteController.php | /site/about | E:/yii2/modules/user/views/site/about.php | 
     
      PS:如果不指定模版的后缀名,默认为”.php”。
     
    
3.$this在不同地方的意义。在VIEW层的$this就是yii/web/view;在CONTROLLERyii/web/controller,所以不可以在view层用render跳转
4.对于URL**和HTML的用法
(1)YII有一些助手类,HTML是可以生成一些HTML代码的类。例如在上面实例中HTML::a就是生成了一个a标签。而对于这个的实现其实就是调用内部的HTML::tag。所以也可以直接用这个实现。举个例子:
 Html::img( '/abc/image1.jpg', [ 'alt' => '头像' ] )这个是一个生成HTML中img标签,框架在实现的函数:
  public static function img($src, $options = [])
    {
        $options['src'] = Url::to($src);
        if (isset($options['srcset']) && is_array($options['srcset'])) {
            $srcset = [];
            foreach ($options['srcset'] as $descriptor => $url) {
                $srcset[] = Url::to($url) . ' ' . $descriptor;
            }
            $options['srcset'] = implode(',', $srcset);
        }
        if (!isset($options['alt'])) {
            $options['alt'] = '';
        }
        return static::tag('img', '', $options);
    }可以看到这里最后一行还是返回一个静态的tag函数:
 public static function tag($name, $content = '', $options = [])
    {
        if ($name === null || $name === false) {
            return $content;
        }
        $html = "<$name" . static::renderTagAttributes($options) . '>';
        return isset(static::$voidElements[strtolower($name)]) ? $html : "$html$content</$name>";
    }所以也可以写作:
<?= Html::tag('img') ?>
后面也可以添加参数,但是注意第二个参数在img标签的时候为空,因为是图像标签没有文字内容。图片源和文字说明都是作为第三个参数填入的。HTML在生成标签的时候还有lable、button、input等等常用标签。
(2)HTML助手类在使用的时候,对于标签嵌套的时候要注意使用参数。例如在ul标签中嵌套li的时候,li的内容要防止编码要注意可以在ul()使用第二个参数:
 public static function ul($items, $options = [])
    {
        $tag = ArrayHelper::remove($options, 'tag', 'ul');
        $encode = ArrayHelper::remove($options, 'encode', true);
        $formatter = ArrayHelper::remove($options, 'item');
        $separator = ArrayHelper::remove($options, 'separator', "\n");
        $itemOptions = ArrayHelper::remove($options, 'itemOptions', []);
     例如:
     
     不想被转义就应该用
     
      Html::ul($arr, ['encode' => false]);
     
(3)Url 帮助类提供一系列的静态方法来帮助管理 URL。和HTML一样都是助手类,在使用的时候都需要use下该类。例如:use yii\helps\Url;
关于这个类比较常用的就是to和toRoute
     (I)关于toRoute—-
     
      获取某一地址
     
    
看下官网上的说法:
为了创建一个给定路由的 URL 地址,请使用 `Url::toRoute()`方法。 
$url = Url::toRoute(['product/view', 'id' => 42]);
你可以指定一个字符串来作为路由,如: site/index 。如果想要指定将要被创建的 URL 的附加查询参数, 你同样可以使用一个数组来作为路由。数组的格式须为:
// generates: /index.php?r=site/index¶m1=value1¶m2=value2
['site/index', 'param1' => 'value1', 'param2' => 'value2']
如果你想要创建一个带有 anchor 的 URL ,你可以使用一个带有 # 参数的数组。比如:
// generates: /index.php?r=site/index¶m1=value1#name
['site/index', 'param1' => 'value1', '#' => 'name']
一个路由既可能是绝对的又可能是相对的。一个绝对的路由以前导斜杠开头(如: /site/index), 而一个相对的路由则没有(比如: site/index 或者 index)。一个相对的路由将会按照如下规则转换为绝对路由:
* 如果这个路由是一个空的字符串,将会使用当前 yii\web\Controller::route 作为路由;
* 如果这个路由不带任何斜杠(比如 index ),它会被认为是当前控制器的一个 action ID, 然后将会把 yii\web\Controller::uniqueId 插入到路由前面。
* 如果这个路由不带前导斜杠(比如: site/index ),它会被认为是相对当前模块(module)的路由, 然后将会把 yii\base\Module::uniqueId 插入到路由前面。
以下是该方法的一些例子:
// /index.php?r=site/index
echo Url::toRoute('site/index');
// /index.php?r=site/index&src=ref1#name
echo Url::toRoute(['site/index', 'src' => 'ref1', '#' => 'name']);
// /index.php?r=post/edit&id=100     assume the alias "@postEdit" is defined as "post/edit"
echo Url::toRoute(['@postEdit', 'id' => 100]);
// http://www.example.com/index.php?r=site/index
echo Url::toRoute('site/index', true);
// https://www.example.com/index.php?r=site/index
echo Url::toRoute('site/index', 'https');稍作整理:有第二个参数且不是URL传递解析的内容就会获得绝对地址,也就是包含协议域名等部分的内容
1://获取某地址 – 相对路径
$url = Url::toRoute(‘site/index’);
2://获取某地址 – 相对路径
$url = Url::toRoute(‘site/index’, false);
说明: 等价于1 因为默认是false
3://获取某地址 – 相对路径
$url = Url::toRoute([‘site/index’, ‘id’ => 1]);
4://获取某地址的 – 绝对路径
$url = Url::toRoute(‘site/index’, true);
5://获取某地址的 -绝对路径
$url = Url::toRoute(‘site/index’, [‘id’ => 1]);
说明: 参数没有输出,说明,这种写法[‘id’ => 1], 他当成了true,所以等价于4
6://获取某地址的 – 绝对路径 (传输协议-http)
$url = Url::toRoute(‘site/index’, ‘http’);
7://获取某地址的 -绝对路径(传输协议-https)
$url = Url::toRoute(‘site/index’, ‘https’);
     (II)关于toRoute—-
     
      创建一个基于给定参数的网址
     
    
同样看下官网的说法:
还有另外一个方法 Url::to() 和 toRoute() 非常类似。这两个方法的唯一区别在于,前者要求一个路由必须用数组来指定。 如果传的参数为字符串,它将会被直接当做 URL 。
Url::to() 的第一个参数可以是:
* 数组:将会调用 toRoute() 来生成URL。比如: ['site/index'], ['post/index', 'page' => 2] 。 详细用法请参考 toRoute() 。
* 带前导 @ 的字符串:它将会被当做别名, 对应的别名字符串将会返回。
* 空的字符串:当前请求的 URL 将会被返回;
* 普通的字符串:返回本身。
以下是一些使用示例:
// /index.php?r=site/index
echo Url::to(['site/index']);
// /index.php?r=site/index&src=ref1#name
echo Url::to(['site/index', 'src' => 'ref1', '#' => 'name']);
// /index.php?r=post/edit&id=100     assume the alias "@postEdit" is defined as "post/edit"
echo Url::to(['@postEdit', 'id' => 100]);
// the currently requested URL
echo Url::to();
// /images/logo.gif
echo Url::to('@web/images/logo.gif');
// images/logo.gif
echo Url::to('images/logo.gif');
// http://www.example.com/images/logo.gif
echo Url::to('@web/images/logo.gif', true);
// https://www.example.com/images/logo.gif
echo Url::to('@web/images/logo.gif', 'https');
稍作整理:有第二个参数且不是URL传递解析的内容就会获得绝对地址,也就是包含协议域名等部分的内容,另外可以引用配置参数是添加的别名
1): //获某网址 – 相对路径
$url = Url::to([‘site/index’]);
2): //获取网址(带参数) – 相对路径
$url = Url::to([‘site/index’, ‘id’ => 1]);
3): 获取当前路径 – 相对路径
$url = Url::to();
4): 获取url – 相对路径
$url = Url::to(‘@web/image/1.jpg’);
说明:它将指定到你的某一个别名目录下@web
5): 获取url – 相对路径
$url = Url::to(‘image/1.jpg’);
6): 获取url – 绝对路径(@mobileUrl 自己配置好的)
$url = Url::to(‘@mobileUrl/image/1.jpg’, true);
7): //获取url -绝对路径(传输协议-https)
$url = Url::to(‘@mobileUrl/image/1.jpg’, ‘https’);
8): //获取url -绝对路径(传输协议-http)
     $url = Url::to(‘@mobileUrl/image/1.jpg’, ‘http’);
     
     (III)current()   remember()    previous()
    
current() 
另外从2.0.3版本开始,你可以使用 yii\helpers\Url::current() 来创建一个基于当前请求路由和 GET 参数的 URL。 你可以通过传递一个 $params 给这个方法来添加或者删除 GET 参数。
// /index.php?r=post/view&id=123&src=google
echo Url::current();
// /index.php?r=post/view&id=123
echo Url::current(['src' => null]);
// /index.php?r=post/view&id=100&src=google
echo Url::current(['id' => 100]);
记住 URLs
有时,你需要记住一个 URL 并在后续的请求处理中使用它。 你可以用以下方式达到这个目的:
// Remember current URL 
Url::remember();
// Remember URL specified. See Url::to() for argument format.
Url::remember(['product/view', 'id' => 42]);
// Remember URL specified with a name given
Url::remember(['product/view', 'id' => 42], 'product');
在后续的请求处理中,可以用如下方式获得记住的 URL:
$url = Url::previous();
$productUrl = Url::previous('product');
检查相对 URLs
你可以用如下代码检测一个 URL 是否是相对的(比如,包含主机信息部分)。
$isRelative = Url::isRelative('test/it');
5.关于render**系列的跳转
render是最长使用的一种跳转方法,必须填写的参数就是跳转去的页面,之后如果需要将参数传过去就可以把参数组成数组的形式传递去页面。然而有一个很明显的问题 ,这里不论你需要不需要都会带着layout中的header个footer一起。有疑问直接去看源码有时候是最快的解决方法。去看下源码:
  public function render($view, $params = [])
    {
        $content = $this->getView()->render($view, $params, $this);
        return $this->renderContent($content);
    }
//上面的函数最后还是调用的下面的方法,
 public function renderContent($content)
    {
//这里加载了布局方法
        $layoutFile = $this->findLayoutFile($this->getView());
        if ($layoutFile !== false) {
            return $this->getView()->renderFile($layoutFile, ['content' => $content], $this);
        }
        return $content;
    }所以我们可以直接自己调用if判断里面的内容去实现,但是对于这地方,YII还是有做考虑的,可以看到一个函数:
 public function renderPartial($view, $params = [])
    {
        return $this->getView()->render($view, $params, $this);
    }这个就是实现了没有布局概念的跳转或者
    public function renderFile($file, $params = [])
    {
        return $this->getView()->renderFile($file, $params, $this);
    }另外有资料说redirect方法是控制器内跳转方法
 public function redirect($url, $statusCode = 302, $checkAjax = true)
    {
        if (is_array($url) && isset($url[0])) {
            // ensure the route is absolute
            $url[0] = '/' . ltrim($url[0], '/');
        }
        $url = Url::to($url);
        if (strpos($url, '/') === 0 && strpos($url, '//') !== 0) {
            $url = Yii::$app->getRequest()->getHostInfo() . $url;
        }
        if ($checkAjax) {
            if (Yii::$app->getRequest()->getIsAjax()) {
                if (Yii::$app->getRequest()->getHeaders()->get('X-Ie-Redirect-Compatibility') !== null && $statusCode === 302) {
                    // Ajax 302 redirect in IE does not work. Change status code to 200. See https://github.com/yiisoft/yii2/issues/9670
                    $statusCode = 200;
                }
                if (Yii::$app->getRequest()->getIsPjax()) {
                    $this->getHeaders()->set('X-Pjax-Url', $url);
                } else {
                    $this->getHeaders()->set('X-Redirect', $url);
                }
            } else {
                $this->getHeaders()->set('Location', $url);
            }
        } else {
            $this->getHeaders()->set('Location', $url);//一般执行这里
        }
        $this->setStatusCode($statusCode);
        return $this;
    }
从代码看,这是直接去对地址发起请求,将得到的结果进行处理。
再来整个梳理下:
(1)remder()
这是带模板的跳转,含带header和footer
(2) renderPartial()
(3)renderFile()
(2)(3)是不带模板的跳转,实际执行的代码一样,可以交替使用。
(4)redirect()
不支持参数POST传递。最后依然是调用header方法.只不过,自定义控制器里的redirect方法,是调用yii\web\Controller里边的redirect方法,然后调用yii\web\Response组件,然后在Response组件里边,调用yii\web\HeaderCollection类里边的get()方法,实现跳转的.或者执行http302重定向。利用这个方法,还可以实现外部服务器请求
另外可以参考YIIChina的部分教程和资料,例如:http://www.yiichina.com/tutorial/819
转载于:https://my.oschina.net/jlong/blog/1607419
 

