This flummoxed me yesterday, and I wonder if anyone can cast any light on the scene for me.
I've got this sort of situation:
class TestCallback {
private $callback;
function __construct($callback){
$this->callback = $callback;
}
// [...]
}
Where I pass a callback into an object as a constructor argument. A method will subsequently need to call that callback. That's fine.
But here's my first attempt at calling the callback:
class TestCallback {
private $callback;
function __construct($callback){
$this->callback = $callback;
}
function callDirect(){
// this single step does not
$this->callback("direct");
}
// [...]
}
$o = new TestCallback(function($type){
printf("called via %s<br>", $type);
});
$o->callDirect();
This errors when I run it, thus:
Fatal error: Call to undefined method TestCallback::callback()
OK, I was doing something wrong. This does not surprise me with PHP one bit (given I'm such a n00b).
Whilst troubleshooting it, I landed on this approach:
function callViaIntermediary(){
$callback = $this->callback;
$callback("intermediary");
}
This works:
called via intermediary
But I don't get it. What is it about assigning the property to an intermediary variable suddenly makes stuff work?
Talking to one of my colleagues, he gave me this alternative, too:
function callViaProxy(){
call_user_func($this->callback, "proxy");
}
This also works fine.
I tried making the property public, and calling it directly:
class TestCallback {
public $callback;
function __construct($callback){
$this->callback = $callback;
}
}
$o = new TestCallback(function($type){
printf("called via %s<br>", $type);
});
$o->callback("public");
This yields the same fatal error as before.
From the error, one can infer that the parser is looking for an actual defined function,
callback()
, eg:function callback(){
// etc
}
And, indeed, if I have that in my class, the code "works" in that the
callback()
method is run.
So it seems to me that whilst
$this->something
refers to a property something
, if if that property value is a function, the one cannot then call that function simply by adding the parentheses: $this->something()
. Because the PHP parser doesn't "get" that. It assumes that something
has to be a declared function. Which doesn't strike me as being correct. Does it?
If I switch back to CFML world, I have this analogous code:
component accessors=true {
property callback;
function init(callback){
setCallBack(callback);
}
function callDirect(){
callback("direct");
}
}
o = new TestCallback(function(type){
writeOutput("called via #type#<br>");
});
o.callDirect();
This works fine, and this is how my expectations are set. I'mnot saying PHP should do what CFML does, just that this is where my expectations lie. I'm a CFML dev, after all.
I'm really bemused in PHP why this doesn't work:
$this->callback("direct");
But this does:
$callback = $this->callback;
$callback("intermediary");
Or is it simply a shortfall of the parser? The combination of
->
and ()
don't make sense to it?Any thoughts?
Cheers.
--
Adam