之前写过一个扩展去实现这个功能,后来发现太麻烦了,直接在_empty方法内部就可以完全实现。
具体步骤如下:
1.在需要这个功能的控制器中定义一个_empty()方法,这个方法是TP控制器内置的空方法处理函数,当访问一个不存在的action时会触发这个函数。
代码如下:
public function _empty(){
try{
if(method_exists($this,"actions")){
$actions = call_user_method("actions", $this);
if(!empty($actions) && is_array($actions) && isset($actions[ACTION_NAME])){
$args = $actions[ACTION_NAME];//构造函数参数
$class = "\\".MODULE_NAME."\\Actions\\".CONTROLLER_NAME."Controller\\".ACTION_NAME."Action";//动作类路径
$action = new ReflectionClass($class);//若类不存在会直接抛出异常
if($action->hasMethod("run")){//检测类是否有run方法
if(count($args) > 0 && $action->hasMethod("__construct")){
$action->newInstance($args)->run($this);
}else{
$action->newInstance()->run($this);
}
}else{
throw new Exception('动作类未定义run方法');
}
}else{
throw new Exception('未发现动作类');
}
}else{
throw new Exception('未定义动作类绑定');
}
}catch(Exception $e){
send_http_status('404');//action不存在或动作类不合法,抛出404
}
}2.在控制器中定义actions()方法,以指定哪些动作需要绑定到类,这里我强烈建议大家在配置文件中指定一下 ACTION_SHUFFIX参数,把动作方法和普通方法区分开来,避免冲突。代码如下:
<?php
namespace Home\Controller;
use Think\Controller;
class Index\Controller extends Controller{
function indexAction(){
echo "hello world";
}
//这里是重点
//返回一个数组,数组格式是 "动作名"=>array(构造函数参数)
function actions(){
return array(
"login"=>array(),//不带构造函数的动作类这里给一个空数组即可
"sendpm"=>array('type'=>'system'),//给动作类构造函数传入一个参数,这个参数是一个array,请从array中根据key值获取具体值
);
}
}3.在当前模块目录下,创建一个Actions目录。4.定义动作类,假设需要为IndexController下的login动作绑定一个类,这时候别再IndexController下定义login()方法了,而是在当前Actions目录下创建一个 IndexController目录,添加loginAction.class.php类。
5.类的格式:
<?php
namespace Home\Actions\IndexController;//这里注意定义命名空间,否则无法加载到这个类,3.2里大量使用了命名空间的特性,所以花点时间掌握它吧。
class loginAction {
function run($controller){
$controller->display();//调用控制器对象的方法
}
}如果带有构造函数:namespace Home\Actions\IndexController;//这里注意定义命名空间,否则无法加载到这个类,3.2里大量使用了命名空间的特性,所以花点时间掌握它吧。
class sendpmAction {
function __construct($args){
$type = $args['type'];//参见actions()方法中定义的sendpm元素
}
function run($controller){
$controller->display();//调用控制器对象的方法
}
}大概流程就是这样。 最佳答案