Warning: Hard Core Dorkage ahead!
I ran into a snag implementing a general callback strategy. The issue is that you can’t use a class name as a variable and then call one of its methods. Here is the backdrop, the boo-boo, and the workaround.
Academic bogus minimal cases:
In PHP it is perfectly fine to do the following:
class Foo { public function query($params) { echo 'in query'; print_r($params); } } $foo = new Foo; $method='query'; $stuff = array('bar'=>'baz', 'voo'=>'param'); $foo->$method($stuff);
However suppose query was a static method and you wanted to call it statically as in
Foo::query($stuff);
When you use a variable for the class or method name and try something such as below
$class='Foo'; $method='query'; $class::$method($stuff);
it gives you a syntax error. Well, crap!
Don’t take no for an answer!
Does this mean you have to take NO for an answer and restrict your callback functions to instance methods of an instantiated object only? Static methods are sometimes preferable. Surely there has to be some sneaky way to do this!!
After some surfing and experimenting, I discovered the following paradigm that works:
class Foo { public static function query($stuff) { echo "in query"; print_r($stuff); } } $class = 'Foo'; $method = 'query'; $stuff = array('bar'=>'baz', 'voo'=>'param'); call_user_func(array($class, $method), $stuff) . "\n";
Gettin’ More Real
In real life you would of course want to fortify this code with tests to make sure that the classes, methods, objects and so forth actually exist and are callable. As the php manual states, simply doing method_exists test will return true even for private methods so it’s better to test is_callable.
Why I want to do this
Maybe this sounds to you like one of those tortured academic examples they come up with in C.S. classes to test the edge cases of a language. Let me assure you that my reason for doing this is very “real world.” I’m building a general statically called retrieve from memcached function using callbacks. If we don’t get a cache hit then we have to call an “expensive query” as a callback. We want to be able to call procedural functions, as well as methods of an instantiated object and static methods. If we can have
$data = Caching::retrieve($key, array('ns'=>$co, 'method'=>$method), $stuff);
where $co can be either a class name or an instantiated object and $stuff is the parameters to the method, we give ourselves maximum flexibility with regard to callbacks.
The goal is encapsulating the logic to test for cache hit within the retrieve method so we don’t have to constantly repeat the the code for the hit test every time we get something out of the memcached. At least that’s the plan for now.
Thanks for the warning. What I just read is a real hardcore dorkage. I couldn’t understand some parts but I got your point here. Developing new stuff to help the old system get better is an admirable quality.
A very useful resource for PHP coding guidelines…
You’re good! I have been slaving myself for few days to find solution for that one last year in my programming class. I have different solution but your’s were elegant than my code.
Hello, I’m searching a solution similar to yours, but for class definition. I need to define the classname from outside the file where it’s defined.
Something like:
$classname = ‘Foo’;
class $classname{
public function query($params){
echo ‘in query’; print_r($params);
}
}
Do you know if it can be done?
Hikari, what happens when you try this?
Can you make a use case for it? Cuz it seems to pervert the idea of a class to my way of thinking. Just as a guess, I think you might do better with an abstract class and various classes that implement it.
coucou,Efficace site s’avère à être tout simplement génial merci bcp Le protocole post. J’apprecie vraiment intensément ce qui m’a vraiment aidé, je recommanderai votre site aux gens que je connais. a bientot.
Very high honor and privilege to landlord’s blog, the article I was very moved.
Hi, i must say fantastic website you have, i stumbled across it in Yahoo. Does you get much traffic? sbbhs2011
Hi everyone, Can someone visit my site vimax 3-4 Dot Com, and tell me if im on the right track? if you guys think i should change it. ill start a fresh on my site again. i need feedback thanks!
Thanks for this well writed post….love your blog!
Hi there, You’ve done a great job. I’ll certainly digg it and personally recommend to my friends. I am sure they will be benefited from this website.
tibia