PHP does not handle my static call correctly

I havinh the problem in PHP 5.3. I need to call a method with __callStatic, but if I use it in an instancied object, call PHP __callinstead.

Above is a real life example:

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

?>

Cachet : Ops! Does not work. Real Ops!

Please note that I am calling useCallStaticfrom new B(). If I call, then it works fine, like B::foo().

What can I do with it, works great?

+3
source share
5 answers

Thinking about it, this is not a mistake. But it is definitely unintuitive.

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

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

$a = new A();
$a->foo();

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

parent::nonExistant() A::__call(), static::nonExistant(). A::__callStatic() ! PHP , . PHP __call .

parent::regularMethod() regularMethod(). ( , :: " ".) parent::staticMethod() A::staticMethod(), .

:

self::__callStatic('foo') .

__call A self::__callStatic.

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

, , , , , .

+7

, , , . , $this __call, , __callStatic?

EDIT: , . php.

+2

-, , PHP 5.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');
?>

(, , ):

A::__call, array (
  0 => 'foo',
  1 => 
  array (
    0 => 'abc',
  ),
)
A::__callStatic, array (
  0 => 'bar',
  1 => 
  array (
    0 => '123',
  ),
)
B::invokeStatic
A::__callStatic, array (
  0 => 'someStatic',
  1 => 
  array (
    0 => '456',
  ),
)

, "!". , , .

PHP ? :

$ php -r 'echo phpversion(), PHP_EOL;'
5.3.3-7+squeeze1
+1

PHP . , __callStatic B

0

Good news

I do BIG work arround, but it works very well. This is the code:

class NoContext {
    public static function call($callback, $args = null){
        return call_user_func_array($callback, $args ?: array());
    }
}

You need to call NoContext::call(statically) what you call call_user_funcor similar. It will remove the context $this. I still think this is a PHP error, but ...

To solve my problem, I:

class B extends A {
    function useCallStatic(){
        NoContext::call('A::foo');
    }
}

And it will print: Fine!.

Thanks to everyone who helps me. I have learned a lot with your answers, and I expect that my advice will be useful to you someday.

0
source

All Articles