Re: Re: PEAR2 Coding standards, Autoloading and Namespaces

From: Date: Sat, 12 Apr 2008 22:14:09 +0000
Subject: Re: Re: PEAR2 Coding standards, Autoloading and Namespaces
References: 1 2 3 4 5 6 7 8  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-49778@lists.php.net to get a copy of this message
On Apr 8, 2008, at 1:56 AM, Christian Weiske wrote:
I'd like to think outside the box, if you could tell me the solution for following problem: - Package MDB3 - Driver packages MDB3_Sqlite, MDB3_MySql etc How do you load those drivers? Currently it was as easy as checking the existence of $path/MDB2/Driver/Sqlite.php and include the file with that name. If every package uses his own namespace, how do you load such a driver? Where do you store it in the file system so that it can be easily found? Making exceptions to the packagename->namespace rule would work, but defeat the purpose of the whole idea.
Well, I have an answer and its somewhat out of the box, too. :) Rather than having a function that "loads" a driver based that driver being in a specific directory (or based on a specific class name), you can use dependency injection to pass the plugin into the class that will use it. Driver Pattern: class Cache { static function getCache($driver, $options = array()) {
    $file = ‘/drivers/’ . $driver . ‘.php’;
    require_once $file;
    $classname = ucfirst($driver) . 'Cache';
    return new $classname($options);
} } class CacheDriverCommon { protected $options; function __construct($options) {
    $this->options = $options;
} } class FileCache extends CacheDriverCommon {} class FeedFetcher { protected $cache; function __construct($options = array()) {
    $this->cache = Cache::getCache(
      $options[‘driver’],
      $options);
} // Do something with $this->cache later } $fetcher = new FeedFetcher(array('cache'=>'file', 'cache_path'=>'/tmp')); With Dependency Injection: interface Cache {
    // ...
} class FileCache implements Cache { protected $path; function __construct($path) {
    $this->path = $path;
} } class FeedFetcher { protected $cache; function __construct(Cache $cache) {
    $this->cache = $cache;
} } $fetcher = new FeedFetcher(new FileCache(‘/tmp’);); The DI version is more modular, more testable (easier to pass a mock object), and getting rid of the options array has some advantages, such as being easier to document, and autocompletion advice in IDEs becomes available for constructor parameters.

« previous php.pear.dev (#49778) next »