Rob
Rob

Reputation: 235

break apart args in magic method __call php

Essentially I am looking to have a universal 'funnel' sort of thing for auto logging. That's the short description, in practice let's say we have a class Controller, now much like in codeIgniter everything is pretty much run through Controller, however I want to create something that will funnel all requests to Controller through this class for universal logging. Here's an example...

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
}

The problem here is the __call method since it makes args an array and if I have to pass 2 args to the controller it ruins everything, i.e.

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

however what if the method needed two arguments like this...

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

if I then called Base->get_stats('2011-01-01', '2013-10-19') everything will break because only 1 arg is passed to the Controller method because of how __call joins all args into one array. Obviously if I know that there will always be 2 args then I vould just get $args[0] and $args[1] but the theory here is to have this as truly dynamic so that all function calls are funneled through the Base class and functions in Controller could have 1-1 million args. Does anyone have any ideas? I have tried call_user_func_array, but it tries to call all methods from a class in a static manner, i.e.

//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);
}

would throw an error because the method in Controller is non static. I am at a loss but I really want to make this work, so any ideas? Please, and thank you.

Upvotes: 0

Views: 932

Answers (1)

h2ooooooo
h2ooooooo

Reputation: 39532

call_user_func_array should work completely fine, so you must be doing something wrong elsewhere in your code:

<?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);
?>

Outputs:

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

DEMO

Upvotes: 1

Related Questions