头像图片

严颖的个人博客

Yii2框架一个不解之处:控制器action被加载两次

这个问题是昨天开发中无意的发现的。我的本意是做一个文章的访问+1功能,也就是页面访问一次,那么访问量+1.(如果不想看解决问题过程,直接拉到文章尾部看结论

发现问题

不过,说来奇怪。当时,我做完了,测试发现,每次访问,数据库的访问量都会+2。噗噗噗,我就奇怪了。开始猜想以为是模型被调用了两次,所以那个值才被加了2。但是排查来排查去,发现我根本没有加载两次模型。

排查问题

于是我打印了页面访问的前后阅读量值,发现:每当控制器有输出,比如echo 123或者var_dump,这个问题也就不会出现。而,没有输出时候,问题立马出现。

于是我把模型注释掉,开始排查。后来发现,只要我删除return $this->render('index');代码,也就是不渲染模板,那么控制器就不会被执行两次。

我于是又开始怀疑,是加载了layout和view视图导致加载两次导致该问题。不过如果是这样,这个框架设计也是很不合理,我觉得不是这个问题。

既然控制器输出问题就不能复现。我于是就使用了在action中使用随机写入文件方法。发现,每次访问页面控制器,都会生成两个随机文件,(代码如下),也就是说是控制器被加载了两次。

public function actionIndex()
{
    file_put_contents(rand(10000,99999).'.txt','123');
    $sour = Source::findLasterList(50);
    return $this->render('index',['sour_list'=>$sour]);
}

视图为什么会影响控制器?

1、html标签有问题,不过按理来说可能性不大。2、视图中加载的php代码影响了控制器。

排查php代码

我去除了页面里面的所有php相关代码,结果发现,问题依然存在,很简单的排除了php的可能。

排查html代码

我首先去官网下载了一个全新的框架,发现官网并没有这个问题。并且,当我用官网的layout代码覆盖我本地的layout时候,问题就迎刃而解。

也就是说,问题出在layout页面。解决问题办法就是把相同的代码都去掉,然后看剩余的代码,依次排除。一行一行比对后,发现只有一行代码不一样,就是我比官方框架在头部head区多了一行代码。

<link rel="icon" href="">

于是我把这行代码复制到官方框架中,发现官方框架的控制器action立马也执行了两次。问题,就在这里,不过,其他网站也有这行代码,如果不能有这行代码,那么这个框架就有问题。所以我试着给这个代码的href填写一个链接值。问题解决了。

结论

所以遇到和我相同的情况,控制器被加载了两次,你只需要删除<link rel="icon" href="">,或者给href添加一个值就可以了。

这个问题,出现的时候,框架并没有报任何的错误。代码运行也十分正常。只有在某些特殊需求的情况下,才能偶然发现该问题。所以网上资料比较少。不知道是不是应该算是一个BUG