Thursday, September 28, 2017

Small Dependency Injection

File: main.php

require 'configure.php';
require 'di.php';
require 'config.php';
require 'db_service.php';
require 'data_model.php';

$db = configure::get('di')->get_service('db');

$data_model = new data_model($db);
$data_model->show_data();

File: configure.php

final class configure {
 /**
  * @var array $config All configured settings handled by this class
  */
 private static $config = array(); 
  
 /**
  * Protected constructor to prevent instance creation
  */
 protected function __construct() { }
 
 /**
  * Fetches a setting set from using Configure::set() or add or update
  *
  * @param string $name The name of the setting to get
  * @param string $key [optional] The Array Key to fetch
  * @return mixed The setting specified by $name, or null if $name was not set
  * 
  * return type: ?array
  */
 public static function get(string $name, $key = false) {
   if (isset(self::$config[strtolower($name)])) {
      $a = self::$config[strtolower($name)];
      if ($key === false) {
         return $a;
      } 
      if (isset($a[$key])) {
         return $a[$key];
      }
   }
   return null;
 }
  
 /**
  * Checks if the setting exists
  *
  * @param string $name The name of the setting to check existance
  * @return boolean true if $name was set, false otherwise
  */
 public static function exists(string $name): bool {
    if (array_key_exists(strtolower($name), self::$config)) {
       return true;
    }
    return false;
 }

  /**
   * Overwrite/Update/Add to $config
   * @param string $name the main key to update
   * @param string $key the sub key
   * @param type $value the data to update
   */
  public static function update(string $name, string $key, $value): void {
 self::$config[strtolower($name)][strtolower($key)] = $value;
  }
  
  /**
   * Add to existing data without loss... to $config
   * @param string $name the main key
   * @param string $key the sub key
   * @param type $value new data to add
   */
  public static function add(string $name, string $key, $value): void {
 self::$config[strtolower($name)][strtolower($key)][] = $value;
  }
    
 /**
  * Frees the setting given by $name, if it exists. All settings no longer in
  * use should be freed using this method whenever possible
  *
  * @param string $name The name of the setting to free
  */
 public static function free(string $name): void {
    if (self::exists($name)) unset(self::$config[strtolower($name)]);
 }
 
 /**
  * Adds the given $value to the configuration using the $name given
  *
  * @param string $name The name to give this setting. Use Configure::exists()
  * to check for pre-existing settings with the same name
  * @param mixed $value The value to set
  */
 public static function set(string $name, $value): void {
    self::$config[strtolower($name)] = $value;
 }
 
}

file: di.php

final class di {
 protected $services = [];
 
 public function register(string $service_name, callable $callable): void {
  $this->services[$service_name] = $callable;
 }
 
 public function get_service(string $service_name, array $args = [] ) {
  if (! array_key_exists($service_name, $this->services)) {
   throw new \Exception("The Service: {$service_name} does not exists.");
  }
  return $this->services[$service_name]($args);
 }
 
 public function __set(string $service_name, callable $callable): void {
  $this->register($service_name, $callable);
 }
 
 public function __get(string $service_name) {
  return $this->get_service($service_name);
 }
 
 public function list_services_as_array(): array { 
  return array_keys($this->services); 
 }
 
 public function list_services_as_string(): string { 
  return implode(',', array_keys($this->services)); 
 }
 
}

configure::set('di', new di());

file: config.php

configure::set('database', array(
  'TYPE' => 'mysql',
  'HOST' => 'localhost',
  'PORT' => '3306',
  'NAME' => 'MyCoolDB',
  'USER' => 'root',
  'PASS' => 'BatMan55', 
));

file: db_service.php

configure::get('di')->register('db', function() {
 $db_info = configure::get('database');
 $db_socket = (isset($db_info['SOCKET'])) ? $db_info['SOCKET'] : false;
 $db_conn = (! empty($db_socket)) ? ":unix_socket={$db_socket};" : "host={$db_info['HOST']};";
 $dsn = "{$db_info['TYPE']}:{$db_conn}port={$db_info['PORT']};dbname={$db_info['NAME']}";
 return new \pdo($dsn, $db_info['USER'], $db_info['PASS']);
});

file: data_model.php

class data_model {

 private $db;
 
 public function __construct(PDO $db) {
  $this->db = $db;
 }
 
 public function show_data(): void {
  $q = $this->db->query("SELECT `data` FROM `test`");

  foreach($q as $row) {
   echo $row['data'] . "<br>";
  }
 }
 
}

If, you do not want to do a bunch of require statements to load all the code up front...

Try Aura.Di
Please leave a comment below, how do you use DI with a framework?

No comments:

Post a Comment