6

I'm trying to call a static magic function (__callStatic) from a member of its child class. Problem being, it goes to the non-static __call instead.

<?php

ini_set("display_errors", true);

class a
{
    function __call($method, $params)
    {
        echo "instance";
    }

    static function __callStatic($method, $params)
    {
        echo "static";
    }
}

class b extends a
{
    function foo()
    {
        echo static::bar();
        // === echo self::bar();
        // === echo a::bar();
        // === echo b::bar();
    }
}

$b = new b();
echo phpversion()."<br />";
$b->foo();

?>

Output:

5.3.6
instance

How can I make it display "static"?

12
  • 1
    Seems like it is impossible, I found this discussion: allegro.cc/forums/thread/607508/919970. Commented Jul 19, 2011 at 16:05
  • 1
    Here: Interestingly, PHP 5.3.3 gives __callStatic priority, but that behavior was reverted back in PHP 5.3.4. Commented Jul 19, 2011 at 16:10
  • 2
    possible duplicate of PHP is handling incorrectly my static call Commented Jul 19, 2011 at 16:12
  • 1
    Lazlo Bonin, keep in mind you're dealing with object inheritance here. Even you think you have two classes, this is actually one. And that one class is not called statically if you do this: $b->foo();. That's not a static function call. The hack would be to do this instead: $b::foo();. Try it for yourself. Commented Jul 25, 2011 at 23:56
  • 1
    @hakre: Or b::foo(); for that matter. Commented Jul 26, 2011 at 12:20

2 Answers 2

8
+50

If you remove the magic method '__call', your code will return 'static'.

According to http://php.net/manual/en/language.oop5.overloading.php "__callStatic() is triggered when invoking inaccessible methods in a static context".

What I think is happening in your code is that,

  1. You are calling static method from a non-static context.
  2. The method call is in non-static context, so PHP searches for the magic method '__call'.
  3. PHP triggers the magic method '_call' if it's exists. Or, if it's not exists it will call '_callStatic'.

Here is a possible solution:

class a
{
    static function __callStatic($method, $params)
    {
        $methodList =  array('staticMethod1', 'staticMethod2');

        // check if the method name should be called statically
        if (!in_array($method, $methodList)) {
            return false;
        }

        echo "static";

        return true;
    }

    function __call($method, $params)
    {
         $status = self::__callStatic($method, $params);
         if ($status) {
             return;
         }
         echo "instance";
    }

}

class b extends a
{
    function foo()
    {
        echo static::staticMethod1();
    }

    function foo2()
    {
        echo static::bar();
    }
}

$b = new b();
echo phpversion()."<br />";
$b->foo();
$b->foo2();
Sign up to request clarification or add additional context in comments.

1 Comment

+1 for "If you remove the magic method '__call', your code will return 'static'." and the nice explanation.
1

In PHP there are the reserved words self and parent for accessing static methods from within a class and/or instantiated object. parent refers to inherited methods from the parent class.

class b extends a
{
    function foo()
    {
        echo parent::bar();
    }
}

EDIT: Uhm, that doesn't do the trick… (using PHP 5.3.5)

$b = new b();
$b->foo();  // displays: instance
a::bar();   // displays: static

2nd EDIT: Ha, it works only, if you omit the __call()-method in class a.

class a
{
    static function __callStatic($method, $params)
    {
        echo "static";
    }

//  function __call($method, $params)
//    {
//        echo "instance";
//    }
}

class b extends a
{
    function foo()
    {
        echo parent::bar();
    }
}

$b = new b();
$b->foo();  // displays: static
a::bar();   // displays: static

2 Comments

Replaced with echo self::bar();, still displaying "instance".
Well, yeah, but I have a __call method in my design that I need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.