PHP错误地处理了我的静态调用

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}";

我在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}";
        }

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

?>

打印:操作!不管用。真正的行动

注意,我从a
newb()调用
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');
    }
}