如何在PHP中创建动态方法?

时间:2010-03-29 14:26:42

标签: php activerecord overloading

我正在尝试使用一些动态方法扩展我的ActiveRecord类。我希望能够从我的控制器中运行它

$user = User::find_by_username(param);
$user = User::find_by_email(param);

我已经阅读了一些关于超载的内容,并认为这是关键。我的AR类中有一个static $_attributes,在这种情况下我通过复制我的模型(User = users)得到了表名。

我该怎么做?所有模型都扩展了ActiveRecord类。

2 个答案:

答案 0 :(得分:2)

您必须使用__callStatic() magic method,它以PHP5.3

的形式提供
public static function __callStatic($name, $arguments) {
/*
    Use strpos to see if $name begins with 'find_by'
    If so, use strstr to get everything after 'find_by_'
    call_user_func_array to regular find method with found part and $arguments
    return result
*/
}

答案 1 :(得分:0)

这也可能有用,它更复杂,但它允许真正的动态函数访问成员变量。

class DynamicFunction {
    var $functionPointer;
    var $mv = "The Member Variable";

    function __construct() {
        $this->functionPointer = function($arg) {
            return sprintf("I am the default closure, argument is %s\n", $arg);
        };
    }

    function changeFunction($functionSource) {
        $functionSource = str_replace('$this', '$_this', $functionSource);
        $_this = clone $this;

        $f = '$this->functionPointer = function($arg) use ($_this) {' . PHP_EOL;
        $f.= $functionSource . PHP_EOL . "};";
        eval($f);
    }

    function __call($method, $args) {
        if ( $this->{$method} instanceof Closure ) {
            return call_user_func_array($this->{$method},$args);
        } else {
            throw new Exception("Invalid Function");
        }
    }
}

if (!empty($argc) && !strcmp(basename($argv[0]), basename(__FILE__))) {
    $dfstring1 = 'return sprintf("I am dynamic function 1, argument is %s, member variables is %s\n", $arg, $this->mv);';
    $dfstring2 = 'return sprintf("I am dynamic function 2, argument is %s, member variables is %s\n", $arg, $this->mv);';

    $df = new DynamicFunction();
    $df->changeFunction($dfstring1);
    echo $df->functionPointer("Rabbit");

    $df->changeFunction($dfstring2);
    $df->mv = "A different var";
    echo $df->functionPointer("Cow");
};