Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
允许动态和静态调用PHP函数_Php_Methods_Dynamic_Static_Chaining - Fatal编程技术网

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

允许动态和静态调用PHP函数,php,methods,dynamic,static,chaining,Php,Methods,Dynamic,Static,Chaining,我正在构建一个应用程序,我需要能够链接方法,所以我需要能够动态和静态地调用方法 例如: $results = Class::where('something') ->where('something else'); 在这种情况下,需要静态和动态调用方法“where”,并且仍然允许链接 我知道Laravel有这样的东西,但我不知道如何实现这样的东西。我只是惊讶于自己证明了这确实是可能的: <?php class Test { private s

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

例如:

$results = Class::where('something')
                ->where('something else');
在这种情况下,需要静态和动态调用方法“where”,并且仍然允许链接


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

我只是惊讶于自己证明了这确实是可能的:

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

但在我看来,这是难以置信的糟糕风格

我只是惊讶于自己证明了这确实是可能的:

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

但在我看来,这是难以置信的糟糕风格

纯粹出于兴趣,我找到了一种方法,使用
\uuu call
\uuu callStatic
并将要调用的方法设置为调用它的范围无法访问(即将方法设置为
private
protected

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

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();
输出: 但是,静态对象在先前被调用后仍保留其属性(请注意两个
orange
字符串)。如果这是不需要的,我们可以通过调用
getNewStationInstance()
强制重置它:

输出:
出于纯粹的兴趣,我找到了一种方法,使用
\uuu call
\uuu callStatic
并将要调用的方法设置为调用它的范围无法访问(即将方法设置为
private
protected

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

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();
输出: 但是,静态对象在先前被调用后仍保留其属性(请注意两个
orange
字符串)。如果这是不需要的,我们可以通过调用
getNewStationInstance()
强制重置它:

输出:
请提供更多代码:),无论如何,如果您想这样做,您必须从
where
函数返回您的对象如果您知道Laravel会这样做,为什么不直接查看Laravel代码呢?拉威尔使用正面。对facade
Class::where('something')
的静态调用返回另一个类的实例,该类的
->where('something')。作为旁注,您误用了术语“动态调用”。他想实现这个li ke Laravel,他没有使用Laravelmore代码,请:),无论如何,如果您想这样做,您必须从
where
函数返回您的对象如果您知道Laravel这样做,为什么不简单地看一下Laravel代码?拉威尔使用正面。对facade
Class::where('something')
的静态调用返回另一个类的实例,该类的
->where('something')。作为旁注,您误用了术语“动态调用”。他想要实现这个Like Laravel,他没有在问题中使用Laravelit is
Class::where('something')
。Not
$class::where('something')
对不起,我不得不修改答案,前一个版本似乎有效,修复了这个问题。这归功于@Bamar和他的回答!因为我的答案可能与你原来的答案不一样,所以我删除了我的答案。你可以让销售代表计算出获胜的组合。Singleton所有DB类@Sammitch这是你对世界的总体看法吗?或者这与这个主题有什么关系吗?这是问题中的
Class::where('something')
。Not
$class::where('something')
对不起,我不得不修改答案,前一个版本似乎有效,修复了这个问题。这归功于@Bamar和他的回答!因为我的答案可能与你原来的答案不一样,所以我删除了我的答案。你可以让销售代表计算出获胜的组合。Singleton所有DB类@Sammitch这是你对世界的总体看法吗?或者这和这个话题有什么关系?
MethodTest::method1()::method2('plum')::method1()::getNewStaticInstance()::method1();
watermelon plum watermelon