PHP错误地处理了我的静态调用
我在PHP5.3上遇到了一个问题。我需要使用PHP错误地处理了我的静态调用,php,class,methods,static,php-5.3,Php,Class,Methods,Static,Php 5.3,我在PHP5.3上遇到了一个问题。我需要使用\uuu callStatic调用一个方法,但是如果我在实例化对象中使用它,PHP将调用\uu call 上面是一个真实的例子: <?php class A { function __call($method, $args){ // Note: $this is defined! echo "Ops! Don't works. {$this->c}";
\uuu callStatic
调用一个方法,但是如果我在实例化对象中使用它,PHP将调用\uu call
上面是一个真实的例子:
<?php
class A {
function __call($method, $args){
// Note: $this is defined!
echo "Ops! Don't works. {$this->c}";
}
static function __callStatic($method, $args){
echo 'Fine!';
}
}
class B extends A {
public $c = 'Real Ops!';
function useCallStatic(){
static::foo();
// === A::foo();
// === B::foo();
}
}
$foo = new B();
$foo->useCallStatic();
// This works:
// B::foo();
?>
打印:操作!不管用。真正的行动
注意,我从anewb()调用useCallStatic
。如果我直接调用,则可以像B::foo()
一样正常工作
我能对它做些什么很好?这可能是因为调用父方法的标准符号,而不管状态如何。您可以检查$this
关键字是否在\uuu call
方法中设置,如果未设置,请调用\uu callStatic
编辑:这本身不是一个bug,静态调用是从对象上下文进行的。看看。静态方法的继承在PHP中有点奇怪。我怀疑您需要在B
中重新定义\uu callStatic
,仔细考虑后,它其实不是一个bug。但这绝对是不直观的
<?php
class A
{
public function foo()
{
static::bar();
}
public function bar()
{
echo "bar()\n";
}
}
$a = new A();
$a->foo();
parent::nonExistant()
方法调用A::\u call()
,就像static::nonExistant()
一样。为任一调用调用调用A::\u callStatic()
都同样有效!PHP无法知道要调用哪一个。然而,根据设计,当从这种上下文调用时,PHP为\u call
提供了优先级
parent::regularMethod()
调用非静态函数regularMethod()
。(同样,::
操作符并不意味着“调用此静态函数”。)同样,parent::staticMethod()
调用A::staticMethod()
要解决您的问题:
您可以在继承的类中手动调用self::uu callStatic('foo')
或者在class A的\u call
方法中,根据已知列表过滤并调用self::\u callStatic
function __call($f, $a)
{
if ($f == 'foo')
return self::__callStatic($f, $a);
else
{
}
}
这很难看,但至少扩展类的人不需要做任何特殊的事情。首先,确保您使用的是PHP5.3.0或更高版本,因为那时才实现了callStatic。这一切似乎都按预期运行,请参见以下示例:
<?php
class A {
public function __call($method, $args) {
echo 'A::__call, ' .
var_export(array($method, $args), true), PHP_EOL;
}
/** As of PHP 5.3.0 */
public static function __callStatic($method, $args) {
echo 'A::__callStatic, ' .
var_export(array($method, $args), true), PHP_EOL;
}
}
$a = new A;
$a->foo('abc');
A::bar('123');
class B extends A {
function invokeStatic($args) {
echo 'B::invokeStatic', PHP_EOL;
self::someStatic($args);
}
}
$b = new B;
$b->invokeStatic('456');
?>
当我运行上面的示例时,我只得到“Fine!”作为唯一的输出,这正是我所期望的
你到底在运行什么版本的PHP?您可以通过以下方式进行检查:
$ php -r 'echo phpversion(), PHP_EOL;'
5.3.3-7+squeeze1
好消息
我在附近做了一件大事,但效果很好。代码如下:
class NoContext {
public static function call($callback, $args = null){
return call_user_func_array($callback, $args ?: array());
}
}
您需要调用NoContext::call
(静态)就像调用call\u user\u func
或类似函数一样。它将删除$this
上下文。我仍然认为这是一个PHP错误,但是
为了解决我的问题,我会:
class B extends A {
function useCallStatic(){
NoContext::call('A::foo');
}
}
它会打印:很好代码>
谢谢所有帮助我的人。我真的从你的回复中学到了很多,我等着我的提示对你有用。如果你让useCallStatic()
static怎么办?乍一看,这似乎是个bug。如果您删除\u调用
,它工作得很好。@Bolt它工作得很好,但问题是我真的需要调用objective,有一次我会在useCallStatic
上使用$this
,而不是在foo
@Kon上使用!如果我把它移除,效果很好。我真的认为这是一个错误。但我没有发现PHP上的bug。&我自己。这不是一个bug,尽管它看起来有点像一个bug。我们必须记住,::
在类方法的上下文中并不意味着“调用此静态函数”,而只是“在解析要使用的类之后调用此函数”。\u调用
方法恰好优先于\u调用静态
方法,如果两者都合适的话。@Jaitsu我不能<代码>\u调用
也很重要,我需要在某些时刻使用它。可以检查是否是静态调用吗?如果您检查是否设置了$this
(即isset($this)
),那么您可以确定它是否是静态调用($this
不会在静态调用中设置)@Jaitsu它是,但是$this
也被定义了:(我以前尝试过这个。关于…$Is\u static=!(isset)呢($this)和&get\u class($this)==\uu class\uuu)
。废话,我忘了这是一个非静态方法。。。hmm@Jaitsu不工作。static::foo
和$this->foo
返回相同的(true
).我不能重新定义,这是我正在开发的一个框架。要求用户重新定义一个方法有点烦人,但是如果你重新定义了,它会像预期的那样工作吗?我想另一个解决方案是使用反射并找出哪些函数是静态的?真的绝对有必要使用\u call
吗?我不是一个超级粉丝,因为比如这些疯狂的问题和暗含的魔力。也许就等着我们得到特质吧?如果我重新定义,它就不起作用了。/第二个建议很好(也许我会用它)但是,如果在这种情况下不存在静态方法,我就无法处理\uu callStatic
来显示错误,例如。如果升级到5.3.4,就不会出现这种行为。在类方法中调用这些方法时,都不意味着“调用静态函数”:parent::foo()
,self::foo()
,static::foo()
。它们只是指在解析:
运算符左侧的对象后调用函数foo()
。如果定义了\uuuu call
和\uuuu callStatic
,并且您在非静态上下文中调用,则前者优先。这两种方法都不是“正确”或“错误”因为这是一个模棱两可的调用。至少通过给\uuuu call
优先级,你可以按照我的回答将调用转发到\uuuu callStatic
。有趣的是,我刚刚在PHP5.3.6上进行了测试,正如你们两位所指出的,静态分辨率确实发生了变化(而且IMHO,感觉崩溃了)。\uu callStatic()
是让PHP处理ro
class NoContext {
public static function call($callback, $args = null){
return call_user_func_array($callback, $args ?: array());
}
}
class B extends A {
function useCallStatic(){
NoContext::call('A::foo');
}
}