OK, let's say you want to load the script configuration. This configuration can be saved in the database file / XML / INI / YAML. Each driver must implement some interface; let it be its ConfigurationLoader .
interface ConfigurationLoader { public function load(); public function get($key, $default = null); } // The final usage of the code: $configuration = new XMLConfiguration('./some/file.xml'); $configuration = new YAMLConfiguration('./some/file.yaml'); $configuration = new DatabaseConfiguration($dbHandler, 'table_name'); $configuration->load(); echo $configuration->get('abc.def.ghi');
So, now we need to implement our drivers. The first thing you should notice is that file-based drivers probably work the same way. The only difference is that each of them parses file sources differently. On the other hand, the database driver works in a completely different way.
class DatabaseConfiguration implements ConfigurationLoader { protected $config = array(); protected $pdo, $tableName; public function __construct(PDO $dbHandler, $tableName) { $this->pdo = $pdo; $this->tableName = $tableName; } public function load() { $this->config = ; } public function get($key, $default = null) { return array_key_exists($this->config, $key) ? $this->config[$key] : $default; } }
Now we need to implement the XML, INI and YAML driver. They all work almost the same way, so ... let them create some abstract class that will handle the general code:
abstract class FileConfiguration implements ConfigurationLoader { // Each file-based configuration loader has a constructor that takes file name as first argument protected $filename; public function __construct($filename) { $this->filename = $filename; $this->getFileContents(); } // Each file-based driver has to store file content protected $fileContent; protected function getFileContents() { $this->fileContents = file_get_contents($this->filename); } // Each driver will have to implement its own implementation of load(). // XMLConfiguration will parse XML, INIConfiguration will parse INI etc. abstract public function load(); // However all of them will store parsed configuration in $config array: protected $config = array(); public function get($key, $default = null) { return array_key_exists($this->config, $key) ? $this->config[$key] : $default; } }
FileConfiguration must be abstract because it does not know how to parse the contents of a file. Only the delivered classes know how to do this:
class XMLConfiguration extends FileConfiguration { public function load() { $xml = simplexml_load_string($this->fileContents); foreach ($xml->root as $config) { $this->config[(string) $config->key] = (string) $config->value; } } } class YAMLConfiguration extends FileConfiguration { public function load() { $yaml = new SomeYAMLParser($this->fileContents); foreach ($yaml->parse() as $config) { $this->config[$config['key']] = $config['value']; } } } class INIConfiguration extends FileConfiguration { public function load() { ... } }
As you can see in this example, there may be another abstract class AbstractConfiguration that stores the $config property and the get($key, $default = null) method, and this will be the parent class for DatabaseConfiguration and FileConfiguration .