第二层内功 - Action ¶
作者:KK
发表日期:2017.4.8
说在前面 ¶
MVC模式下我们通常第一时间就在控制器的方法里写代码,在Yii里将这个写代码的地方定义了一个叫Action
的概念,比如下面就有2个Action:
class UserController extends \yii\web\Controller{
public function actionRegister(){
//注册处理
}
public function actionLogin(){
//登录处理
}
}
我们日常交流中就说“这个控制器里有2个方法分别处理注册和登录业务”,在Yii里应该说“这个控制器里有2个Action……”
方法就方法,干嘛要套个别的名头上去?且看下面
Action映射 ¶
先定义一个类继承yii\base\Action:
namespace app\actions;
class Login extends \yii\base\Action{
public function run(){
echo '登录处理';
}
}
然后控制器可以这样:
class UserController extends \yii\web\Controller{
//这个方法是重点!!!!
public function actions(){
return [
//将login映射到指定的类
'login' => 'app\actions\Login'
];
}
public function actionRegister(){
//注册处理
}
}
此时看上去只有?r=user/register
能访问到actionRegister方法
但实际上?r=user/login
也能访问,它会执行app\actions\Login::run,因为控制器的actions
方法进行了actionID映射,它里面的意思是说:如果收到请求的actionID是login
的话,那就大概这样:
$action = new \app\actions\Login();
$action->run();
这样就实现了将login逻辑剥离到一个独立的类里处理了,而且这个类还能被别的地方重用
假如登录逻辑的代码很长很复杂,写在这个Controller那加上别的业务代码量就会变得很大,我们可以尝试这样封装一下,我个人曾经也遇到过这样的项目,登录逻辑很复杂很长,而且登录后又要做一些事情
访问控制器 ¶
如果有多个控制器都定义了actions
方法来映射到同一个Action类,那这个Action怎么知道是哪个控制器调用了自己呢?那就是$this->controller
属性:
echo $this->controller->id;
var_dump($this->controller);
访问actionId ¶
$this->id
返回值 ¶
将业务逻辑封装到独立的Action中后,这个Action处理完业务要返回数据给前端时,做法跟平时控制器的方法是一模一样的,比如return 123
或return $this->controller->render('login')
或renderPartial等都行
属性注入 ¶
其实actions方法进行映射时也能进行属性注入,比如一个Action定义了$a、$b属性,那映射时可以这么来:
public function actions(){
return [
'login' => [
//变成了数组
'class' => 'app\actions\Login',
'a' => 'value a',
'b' => 'value b',
]
];
}
这样如果有多个控制器都将各自的请求映射给同一个Action时,但各个控制器的actions方法可以注入不同的属性值,以此来让这个Action能依据不同的属性值来进行不同的工作逻辑控制
实际上这种需求很少,首先定义成独立Action的需求就很更少,所以这个只要知道一下就好
好了,那为何叫Action ¶
简单地说,如果将login方法定义成了一个独立的类(如上面的app\actions\Login),那这个类已经不能说它是控制器的login方法了
而是login业务通过一个类的逻辑来实现了而已,这个逻辑体叫什么呢,于是官方就起名为Action(行动)