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

Dav*_*ues 3 php methods static class php-5.3

我在PHP 5.3上遇到了问题.我需要通过使用调用方法__callStatic,但如果我在实例化对象中使用它,则调用PHP __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();

?>
Run Code Online (Sandbox Code Playgroud)

打印:行动!不行.真正的行动!

请注意,我打电话useCallStaticnew B().如果我直接打电话就好了B::foo().

我能做些什么呢?

Mat*_*hew 7

在考虑之后,这不是一个真正的错误.但这绝对不直观.

<?php
class A
{
  public function foo()
  {
    static::bar();
  }

  public function bar()
  {
    echo "bar()\n";
  }
}

$a = new A();
$a->foo();
Run Code Online (Sandbox Code Playgroud)

这是有效的,并调用bar().它并不意味着静态调用吧.它意味着查找当前类名和调用函数(bar如果它存在),无论它是否是静态函数.

为了澄清一点:你认为parent::bar()调用静态函数的方法是bar()什么?不,这意味着调用任何命名的函数bar().

考虑:

<?php
class A
{
  function __call($name, $args)
  {
    echo "__call()\n";
  }

  static function __callStatic($name, $ags)
  {
    echo "__callStatic()\n";
  }

  function regularMethod()
  {
    echo "regularMethod()\n";
  }

  static function staticMethod()
  {
    echo "staticMethod()\n";
  }

}

class B extends A
{
  function foo()
  {
    parent::nonExistant();   
    static::nonExistant();
    parent::regularMethod();
    parent::staticMethod(); 
  }
}

$b = new B();
$b->foo();
Run Code Online (Sandbox Code Playgroud)

所述parent::nonExistant()方法调用A::__call(),象static::nonExistant().调用A::__callStatic()任何呼叫也同样是有效的!PHP无法知道您想要调用哪一个.但是,根据设计,PHP __call在从这种上下文中调用时会给出优先级.

parent::regularMethod()调用非静态函数regularMethod().(同样,::运算符并不意味着"调用此静态函数.")同样按照人们的预期parent::staticMethod()调用A::staticMethod().

要解决您的问题:

您可以手动调用self::__callStatic('foo')继承的类.

或者在__callA类方法中针对已知列表和调用进行过滤self::__callStatic.

function __call($f, $a)
{
  if ($f == 'foo')
    return self::__callStatic($f, $a); 
  else
  {
  }
}
Run Code Online (Sandbox Code Playgroud)

这很难看,但至少延伸课程的人不需要做任何特别的事情.