Re: Re: PEAR2 Coding standards, Autoloading and Namespaces
| From: | Jeff Moore | 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.