tags:

views:

5058

answers:

5

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

+8  A: 

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();
Peter Bailey
Thanks, call_user_func does the trick. I note that if the function is passed to a method in the other class then, not unnaturally, it needs to be scoped with 'Bar' instead of 'self'.
Eric
A: 

"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)

Joe
This means that you can't invoke the static method using "$this->", it doesn't mean that you can't pass the static method around in a (effectively function-valued) variable.
Eric
+4  A: 
rewbs
A: 

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

?>
You are just calling Calc(), not storing it in a variable first. Assigning functions to variables and passing them around is useful for writing general purpose algorithms, for example a sort function that accepts different comparison functions for ordering.
Eric
A: 

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

?>
dwallace