I'm building a framework and I'm stuck with a small problem. Well, more than a problem I'd call it a challenge. While building the widget system, I found that I wanted some basic functionality for all of my widgets, namely a build() static method that would allow me to easily instantiate any widget and then chain the next method, like this:
$code = MySpecificWidget::build()->getHTML();
For that, I wrote this code:
abstract class StandardWidget {
public static function build() {
$className = get_called_class(); // the "late static binding" classname
return new $className;
}
}
class MySpecificWidget extends StandardWidget {
public function getHTML() {
return '<b>Some HTML</b>';
}
}
So far so good. But what if the developers were to write widgets that need parameters when constructed?
What I tried to do was this:
abstract class StandardWidget {
public static function build() {
return call_user_func_array(
array(
get_called_class(), // the "late static binding" classname
'__construct' // the method in the target class to invoke
),
func_get_args() // pass along all (if any) of the arguments received
);
}
}
So that you'd only have to write __construct() in the subclass if parameters were needed.
Unfortunately, the PHP parser informed me that __construct() cannot be called statically.
Since I'm writing a framework, I'm trying to be as lightweight as possible. So here's the challenge:
Is there any way of doing this without:
- Using
eval() - Using Reflection
- Having to forcefully write constructors in every subclass
Update
Some more insights of why do I want it like this.
The idea behind it is that most of the time, a widget will be instantiated, then asked to return its HTML and finally destroy itself forever as it is won't be needed anymore. They will most likely be used as parameters inside associative arrays (parameters to be passed along to my templating system), so I think that having them instantiated "anonymously" and in one line would be really useful and code saving.
Widgets cannot be static classes because they may have an internal status (only in that case I won't need to chain its constructor), and in order to avoid it becoming cumbersome (as I don't want every widget to have a constructor if it doesn't need one), I'd like the build method to be in the abstract class from which all widgets inherit.
I think the best way would be the one I wrote above, if only I could invoke the magic constructor like that...