Eric
Eric

Reputation: 11662

Reference to static method in PHP?

In PHP, I am able to use a normal function as a variable without problem, but I haven't figured out how to use a static method. Am I just missing the right syntax, or is this not possible?

(EDIT: the first suggested answer does not seem to work. I've extended my example to show the errors returned.)

function foo1($a,$b) { return $a/$b; }

class Bar
{
    static function foo2($a,$b) { return $a/$b; }

    public function UseReferences()
    {
        // WORKS FINE:
        $fn = foo1;
        print $fn(1,1);

        // WORKS FINE:
        print self::foo2(2,1);
        print Bar::foo2(3,1);

        // DOES NOT WORK ... error: Undefined class constant 'foo2'
        //$fn = self::foo2;
        //print $fn(4,1);

        // DOES NOT WORK ... error: Call to undefined function self::foo2()
        //$fn = 'self::foo2';
        //print $fn(5,1);

        // DOES NOT WORK ... error: Call to undefined function Bar::foo2()        
        //$fn = 'Bar::foo2';
        //print $fn(5,1);

     }
}

$x = new Bar();
$x->UseReferences();

(I am using PHP v5.2.6 -- does the answer change depending on version too?)

Upvotes: 22

Views: 32582

Answers (8)

Jiangge Zhang
Jiangge Zhang

Reputation: 4724

You could use the full name of static method, including the namespace.

<?php
    function foo($method)
    {
        return $method('argument');
    }

    foo('YourClass::staticMethod');
    foo('Namespace\YourClass::staticMethod');

The name array array('YourClass', 'staticMethod') is equal to it. But I think the string may be more clear for reading.

Upvotes: 7

Camilo Martin
Camilo Martin

Reputation: 37918

Coming from a javascript background and being spoiled by it, I just coded this:

function staticFunctionReference($name)
{
    return function() use ($name)
    {
        $className = strstr($name, '::', true);
        if (class_exists(__NAMESPACE__."\\$className")) $name = __NAMESPACE__."\\$name";
        return call_user_func_array($name, func_get_args());
    };
}

To use it:

$foo = staticFunctionReference('Foo::bar');
$foo('some', 'parameters');

It's a function that returns a function that calls the function you wanted to call. Sounds fancy but as you can see in practice it's piece of cake.

Works with namespaces and the returned function should work just like the static method - parameters work the same.

Upvotes: 1

hek2mgl
hek2mgl

Reputation: 158280

In addition to what was said you can also use PHP's reflection capabilities:

class Bar {

    public static function foo($foo, $bar) {
        return $foo . ' ' . $bar;
    }


    public function useReferences () {
        $method = new ReflectionMethod($this, 'foo');
        // Note NULL as the first argument for a static call
        $result = $method->invoke(NULL, '123', 'xyz');
    }

}

Upvotes: 0

dwallace
dwallace

Reputation: 331

In PHP 5.3.0, you could also do the following:

<?php

class Foo {
    static function Bar($a, $b) {
        if ($a == $b)
            return 0;

        return ($a < $b) ? -1 : 1;
    }
    function RBar($a, $b) {
        if ($a == $b)
            return 0;

        return ($a < $b) ? 1 : -1;
    }
}

$vals = array(3,2,6,4,1);
$cmpFunc = array('Foo', 'Bar');
usort($vals, $cmpFunc);

// This would also work:
$fooInstance = new Foo();
$cmpFunc = array('fooInstance', 'RBar');
// Or
// $cmpFunc = array('fooInstance', 'Bar');
usort($vals, $cmpFunc);

?>

Upvotes: 1

eddy
eddy

Reputation:

This seems to work for me:

<?php

class Foo{
    static function Calc($x,$y){
        return $x + $y;
    }

    public function Test(){
        $z = self::Calc(3,4);

        echo("z = ".$z);
    }
}

$foo = new Foo();
$foo->Test();

?>

Upvotes: 0

rewbs
rewbs

Reputation: 1990

In php 5.2, you can use a variable as the method name in a static call, but to use a variable as the class name, you'll have to use callbacks as described by BaileyP.

However, from php 5.3, you can use a variable as the class name in a static call. So:

class Bar
{
    public static function foo2($a,$b) { return $a/$b; }

    public function UseReferences()
    {
        $method = 'foo2';
        print Bar::$method(6,2); // works in php 5.2.6

        $class = 'Bar';
        print $class::$method(6,2); // works in php 5.3
     }
}

$b = new Bar;
$b->UseReferences();
?>

Upvotes: 10

Joe
Joe

Reputation: 7

"A member or method declared with static can not be accessed with a variable that is an instance of the object and cannot be re-defined in an extending class"

(http://theserverpages.com/php/manual/en/language.oop5.static.php)

Upvotes: -3

Peter Bailey
Peter Bailey

Reputation: 105914

PHP handles callbacks as strings, not function pointers. The reason your first test works is because the PHP interpreter assumes foo1 as a string. If you have E_NOTICE level error enabled, you should see proof of that.

"Use of undefined constant foo1 - assumed 'foo1'"

You can't call static methods this way, unfortunately. The scope (class) is relevant so you need to use call_user_func instead.

<?php

function foo1($a,$b) { return $a/$b; }

class Bar
{
    public static function foo2($a,$b) { return $a/$b; }

    public function UseReferences()
    {
        $fn = 'foo1';
        echo $fn(6,3);

        $fn = array( 'self', 'foo2' );
        print call_user_func( $fn, 6, 2 );
     }
}

$b = new Bar;
$b->UseReferences();

Upvotes: 30

Related Questions