Reputation: 11662
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
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
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
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
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
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
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
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
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