PHP 方法可以在实例化和静态上下文中工作?

问题描述 投票:0回答:2

我正在尝试设置一些可在实例化和静态上下文中调用的 PHP 方法。有哪些好的方法可以做到这一点?例如我希望能够做到:

Foo::bar($item); 
foo($item)->bar();

我可以设置两个单独的类,让每个函数修改 thisArg 并委托给另一个函数,但似乎必须有更好的方法。我能想到的只用一堂课来做到这一点的唯一方法是这样的:

function foo($item = null) {
    return $item instanceof Foo ? $item : new Foo($item);
}

class Foo { 
    protected $wrapped;

    public function __construct($item = null) { 
        $this->wrapped = $item;
    }

    public function get() {
        return $this->wrapped;
    }

    public function bar($item = null) {
        isset($this) and $item = &$this->wrapped;
        // do stuff with $item
        return isset($this) ? $this : $item;
    }
}

如果你看一下 underscore.php 的代码,他们会做类似的事情。我不久前读过一些相关的问题,其中指出使用

isset($this)
来确定上下文可能会引发警告,但它似乎工作正常......对此有任何更新的想法吗?另一种可能性是创建两个类,一个类具有方法的所有静态版本,然后第二个类使用 __call 委托给静态方法,例如:

class _Foo
{
        protected $wrapped;

        public function __construct($item = null) { 
            $this->wrapped = $item;
        }

        public function __call($method_name, $args) { 
            array_unshift($args, $this->wrapped);
            $this->wrapped = call_user_func_array('Foo::' . $method_name, $args);
            return $this;
        }


}

想法?

php oop design-patterns methods static-methods
2个回答

0
投票

这是唯一可靠的解决方案。它适用于 5.3+(除了底部的内联对象实例化),但有点笨拙。

class foo {
    protected function __call($method, $args) {
        if ($method == 'bar') {
            return $this->bar($args[0]);
        }
    }
    protected function bar($baz) {
        return "object context: $baz\n";
    }

    public static function __callStatic($method, $args) {
        if ($method == 'bar') {
            return self::barStatic($args[0]);
        }
    }
    protected static function barStatic($baz) {
        return "static context: $baz\n";
    }
}

echo foo::bar('baz');
echo (new foo())->bar('baz');

不推荐: 以下代码在 PHP 5.6 中有效,但在 PHP 7.0 中运行时会抛出

E_DEPRECATED
错误,并显示消息“非静态方法 foo::bar() 不应静态调用”。问题不在于您所说的
isset($this)
,而在于让单个函数执行双重任务:它要么是静态的,要么不是。 PHP 7.0 中仍然支持它,但您不应该依赖它。

class foo {
    public function bar($baz) {
        if (isset($this)) {
            return "object context: $baz\n";
        } else {
            return "static context: $baz\n";
        }
    }
}

echo foo::bar('baz');
echo (new foo())->bar('baz');

不起作用: 这会在 PHP 5.6 和 PHP 7.0 中引发致命错误“Cannot redeclare foo::bar()”,但如果您可以这样做,那就更理想了。

class foo {
    public function bar($baz) {
        return "object context: $baz\n";
    }
    public static function bar($baz) {
        return "static context: $baz\n";
    }
}

echo foo::bar('baz');
echo (new foo())->bar('baz');

也许在未来的版本中,一旦删除了已弃用的用法,我们就可以做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.