On 15/02/2015 19:04, Patrick Schaaf wrote:
In our codebase we have one set of classes where it was very useful to be
able to call the same methods both statically and nonstatically: a set of
wrapper classes over phpredis where subclasses "know" which set of redis
servers to talk to (plus other config like retry strategies and timeouts).
In most cases calling code does not need to be concerned with these details
and just calls methods like red_global::get() or red_local::put().
By neccessity the implementation of this class set, must make use of both
__call() and __callStatic() magic methods, with both then dispatching to a
delegate phpredis instance, and in the case of __callStatic(), making
up-front a singleton like "new self" once. For a set of additional helper
methods (not present on the underlying phpredis) I additionally have a
special mapping array of real method names to internal implementation names.
This sounds to me like you should just be using the Singleton pattern,
at which point you need no magic calls at all. It can even be done as a
subclass of an existing non-static class:
class MyRedis extends Redis {
private static $singleton;
public static function singleton() {
if ( is_null(self::$singleton) ) {
self::$singleton = new self; // may need parameters here
}
return self::$singleton;
}
// Other methods can go here, just like a normal subclass
}
// Now wherever in the code you want the default instance, just use this:
$value = MyRedis::singleton()->get($key);
MyRedis::singleton()->someCustomAction($anotherKey);
The nice thing about an explicit Singleton is you can migrate to
Dependency Injection (call "$redis = MyRedis::singleton()" and start
passing the instance around, until you get to the point where it is only
called once), or to a cleverer factory / service locator (store more
than one instance in different static variables or a keyed array, to
connect to different stores for different purposes).
Making static calls implicitly access a singleton seems like it would
make code harder to read, and harder to extend, in exchange for typing a
few characters on each call (you could call it something shorter, like
"::inst()" if you valued brevity) so a -1 from me.
Regards,
--
Rowan Collins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php