在魔术方法__call php中分解args

时间:2013-10-31 15:24:46

标签: php codeigniter

基本上我希望有一个通用的“漏斗”类型的东西用于自动记录。这是简短的描述,在实践中假设我们有一个类Controller,现在很像在codeIgniter中,一切都是通过Controller运行的,但是我想创建一些东西,通过这个类将所有请求汇集到Controller以进行通用日志记录。这是一个例子......

class Base {
    protected $_controller;

    public function __construct() {
        $this->_controller = new Controller();
    }
    public function __get($key) {
        $this->_logger->log('you are getting '.$key);
        return $this->_controller->$key;
    }
    // and so on for all the magic methods, __set, __get, __call, __callStatic
}

这里的问题是__call方法,因为它使args成为一个数组,如果我必须将2个args传递给控制器​​,它会破坏一切,即

    public function __call($method, $args) {
        //obviously call to logging and make sure method_exists here
        return $this->_controller->$method($args);
    }

但是,如果该方法需要两个这样的参数...

    //this would be inside the Controller
    public function get_stats($start_date, $end_date) {
        //blah blah lots of code here
    }

如果我随后调用Base-> get_stats('2011-01-01','2013-10-19'),一切都会中断,因为只有1个arg传递给Controller方法,因为__call将所有args连接到一个阵列。显然,如果我知道总会有2个args,那么我只能获得$ args [0]和$ args [1],但这里的理论是将它设置为真正的动态,以便所有函数调用都通过Base类进行汇集。 Controller中的函数可以有1-1万个args。 有没有人有任何想法? 我尝试过call_user_func_array,但它尝试以静态方式调用类中的所有方法,即

//inside base class
public function __call($method, $args) {
    //check for function and all that stuff here
   return call_user_func_array(array($this->_controller, $method), $args);
}

会抛出错误,因为Controller中的方法是非静态的。我不知所措,但我真的想做这项工作,所以任何想法?拜托,谢谢。

1 个答案:

答案 0 :(得分:1)

call_user_func_array应该可以正常运行,因此您必须在代码中的其他位置执行错误操作:

<?php
    class Base {
        private $controller;

        public function __construct() {
            $this->controller = new Controller();
        }

        public function __call($method, $arguments) {
            return call_user_func_array(array($this->controller, $method), $arguments);
        }

        public static function __callStatic($method, $arguments) {
            return call_user_func_array(array('Controller', $method), $arguments);
        }
    }

    class Controller {
        public function fooMethod($foo, $bar) {
            return array($foo, $bar);
        }

        public static function barMethod($bar, $foo) {
            return array($bar, $foo);
        }
    }

    $base = new Base();

    $result = $base->fooMethod('foo', 'bar');

    print_r($result);

    $result = Base::barMethod('bar', 'foo');

    print_r($result);
?>

输出:

Array
(
    [0] => foo
    [1] => bar
)
Array
(
    [0] => bar
    [1] => foo
)

DEMO