I need an inherited static function "call" to call another static function "inner" that has been overridden. I could do this with late static binding, but my host does not have php5.3 yet and so I need to work around it.
class ClassA{
static function call()
{
return self::inner();
}
static function inner(){
return "Class A";
}
}
class ClassB extends ClassA{
static function inner(){
return "Class B";
}
}
echo "<p>Class A = " . ClassA::call();
echo "<p>Class B = " . ClassB::call();
I would like the output to be:
Class A = Class A
Class B = Class B
But what it is:
Class A = Class A
Class B = Class A
My gut tells me that I should be able to write something in call() to detect what object was referenced when "call()" was, well, called. So instead of self::inner() it would so something along the lines of calledclass::inner(). Detecting the proper version of inner() to call from the original method call.
You can use object instances rather than classes. If you want a global symbol, you can use a global variable. Since they are rather unwieldy in PHP, one trick is to wrap it in a function. Eg.:
But a better idea might be to avoid global symbols altogether; The reason why it works well in Ruby/Rails, is that Ruby doesn't really have static state in the same way that PHP has. A class can be rebound and added to at runtime, which allows for easy extension of the framework. In PHP, classes are always final, so referring to them in application code, is a very strong degree of coupling.
Unfortunately there is no nice way to do it (otherwise PHPers wouldn't cheer so much for that feature).
You have to pass class name. PHP < 5.3 also doesn't have nice syntax for static calls with dynamic class name which makes whole thing even uglier:
If you can change the code (and not use
static
), then singletons make it more bearable. You can make helper function to ease the syntax:The X function should look up, create and return instance of a class.
Here's a quick example.
If you don't like passing in the class name you could add a static init function to the child class and explicitly pass it there as well. This would allow you to do something like: ClassA::init()->call() and ClassB::init()->call() but would have some minor code duplication.
If performance is not an issue, you can use debug_backtrace() to find the called class:
http://php.net/manual/en/function.debug-backtrace.php
Since you cant use static:: , or get_called_class(), or __callStatic, you'll have to call the inner() function with some indication with the called class (as mentioned in the other answers). An instance of the called class would be fine. You can add "Pseudo Static" methods to mimick every static method you need to overwrite. This doubles your code, but by doing this as below, I hope the code is easier to upgrade once php5.3 comes around: just remove all the ps methods and all the functions referencing them (and change "self" to "static" where needed ..)
Often, late static binding is needed when a child calls back a method of the parent who, in turn, calls an abstract static method of the child. I was in such a postition, and could not use static:: as my PHP was not version 5.3 (or later). The following accomplished late static binding by way of debug_backtrace().