允许动态和静态调用PHP函数

时间:2017-03-30 20:45:14

标签: php methods dynamic static chaining

我正在构建一个应用程序,我需要能够链接方法,所以我需要能够动态地和静态地调用方法。

例如:

$results = Class::where('something')
                ->where('something else');

在这种情况下,方法'其中'需要静态和动态地调用,并且仍然允许被链接。

我知道Laravel与Eloquent有类似的东西,但我不知道如何实现这样的东西。

2 个答案:

答案 0 :(得分:2)

我只是通过证明 确实有可能让我感到惊讶:

<?php
class Test {
    private static $myself;
    public function do() {
        echo isset($this) ? 'd' : 's';
        if (!isset(self::$myself)) {
            self::$myself = new self;
        }
        return self::$myself;
    }
    public static function done() {
        echo PHP_EOL;
    }
}
Test::do()->do()->do()->done();
$myTest = new Test;
$myTest->do()->do()->do()->done();
$myTest::do()->do()->do()->done();
$myTest::do()->do()::do()->done();
Test::do()->do()->do()->done();

输出结果为:

sdd
ddd
sdd
sds
sdd

但是我眼中的风格难以置信......

答案 1 :(得分:0)

出于纯粹的兴趣,我已经找到了使用__call__callStatic执行此操作的方法,并将要调用的方法设置为调用它的范围无法访问(即将方法设置为privateprotected)。

重要警告:使用__call__callStatic可能会导致意外行为!首先阅读here以确保您理解这一点。下面的代码动态执行从类外部调用的私有类方法,因此您需要确保将要添加此行为的特定方法列入白名单。可能还有其他安全问题我没有处理过,因此请自担风险。

class MethodTest
{

    private static $obj;
    private $fruit = 'watermelon';

    private function handleDynamicCallType($name, $arguments)
    {
        switch ($name) {
            case 'method1':
            case 'method2':
                $this->{$name}($arguments);
                break;
            default:
                throw new Exception("Invalid name");
        }
    }

    private function method1() {
        echo $this->fruit . ' ';
    }

    private function method2() {
        $arg_list = func_get_args();
        if (!empty($arg_list[0][0])) {
            $this->fruit = $arg_list[0][0];
        }
    }

    public function __call($name, $arguments)
    {
        $this->handleDynamicCallType($name, $arguments);
        return $this;
    }

    public static function __callStatic($name, $arguments)
    {
        if (!isset(self::$obj)) {
            self::getNewStaticInstance();
        }
        self::$obj->{$name}($arguments);
        return self::$obj;
    }

    public static function getNewStaticInstance()
    {
        self::$obj = new MethodTest();
        return self::$obj;
    }
}

$obj = new MethodTest;
$obj->method1()::method2('orange')->method1();
echo PHP_EOL;
MethodTest::method1()->method2('plum')::method1();

输出:

watermelon orange 
orange plum 

然而,静态对象在被调用之后会保留其属性(请注意两个orange字符串)。如果这是不受欢迎的,我们可以通过调用getNewStaticInstance()强制重置:

MethodTest::method1()::method2('plum')::method1()::getNewStaticInstance()::method1();

输出:

watermelon plum watermelon