Last active
August 29, 2015 14:06
-
-
Save jtarleton/e86a0a7bb480be1412c4 to your computer and use it in GitHub Desktop.
A set of generic data structures for extending the Drupal 7 Database class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* A set of generic data structures for extending the Drupal 7 Database class. | |
* | |
* For non-Drupal projects, you could also use this with PDO. | |
* | |
* Just re-write the BaseObject, BaseEntity, BaseCollection classes. | |
* | |
* | |
* Defining your own data types in PHP is as easy as: | |
* | |
* 1. Create the MySQL table | |
* | |
* CREATE TABLE IF NOT EXISTS concrete ( | |
* id int(100) NOT NULL AUTO_INCREMENT, | |
* name varchar(200) NOT NULL, | |
* ts timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, | |
* PRIMARY KEY (id) | |
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ; | |
* | |
* INSERT INTO concrete (name, ts) VALUES | |
* ('testing', '2014-09-03 21:17:48'); | |
* | |
* 2. Adding a very simple implementation (e.g. for a MySQL table named "concrete"): | |
* | |
* // concrete.class.inc | |
* class Concrete extends BaseObject implements Record | |
* { | |
* protected $tableName = 'concrete'; | |
* protected $pkField = 'id'; | |
* | |
* public function __construct($id) | |
* { | |
* $this->id = (int)$id; | |
* $this->load(); | |
* } | |
* } | |
* | |
* // In your Drupal module | |
* require_once(DRUPAL_ROOT . '/sites/all/libraries/models/drupalstuff.php'); | |
* require_once(DRUPAL_ROOT . '/sites/all/libraries/models/concrete.class.inc'); | |
* | |
* die(var_dump(ConcreteCollection::get(1)->getId())); | |
*/ | |
/** | |
* Specifies mandatory behaviors for classes implementing this interface | |
*/ | |
interface Records | |
{ | |
public static function get($id); | |
} | |
interface Record | |
{ | |
public function getId(); | |
} | |
abstract class BaseEntity extends Database | |
{ | |
public static function db_query($query, array $args = array(), array $options = array()) { | |
if (empty($options['target'])) { | |
$options['target'] = 'default'; | |
} | |
return parent::getConnection($options['target'])->query($query, $args, $options); | |
} | |
public static function db_select($table, $alias = NULL, array $options = array()) { | |
if (empty($options['target'])) { | |
$options['target'] = 'default'; | |
} | |
return parent::getConnection($options['target'])->select($table, $alias, $options); | |
} | |
} | |
abstract class BaseObject extends BaseEntity | |
{ | |
protected $id, | |
$data, | |
$tableName, | |
$tableAlias, | |
$pkField; | |
/** | |
* load : When called from the subclass's constructor, assigns values to properties from a database record | |
* @author | |
* @return void | |
*/ | |
protected function load(){ | |
$this->data = parent::db_select($this->tableName, $this->tableAlias) | |
->fields($this->tableAlias) | |
->condition(sprintf('%s.%s',$this->tableAlias, $this->pkField), $this->id, '=') | |
->execute()->fetchAssoc(); | |
} | |
} | |
/** | |
* BaseCollection is a static class for the returning result sets of objects of type $objectName | |
* | |
* static::$objectName, static::$tableName, static::$tableAlias, static::$pkField are "late static bindings" | |
* See: http://www.php.net//manual/en/language.oop5.late-static-bindings.php | |
* | |
* The "static" keyword references the subclass that was initially called at runtime. | |
*/ | |
abstract class BaseCollection extends BaseEntity | |
{ | |
protected static $objectName, | |
$tableName, | |
$tableAlias, | |
$pkField; | |
public static function getAllByCriteria(array $criteria) | |
{ | |
$query = parent::db_select(static::$tableName, static::$tableAlias) | |
->fields(self::$tableAlias, array(static::$pkField)); | |
foreach ($criteria as $field => $value) { | |
$query->condition(sprintf('%s.%s',static::$tableAlias, $field), $value, '='); | |
} | |
$rows = $query->execute()->fetchAssoc(); | |
$entries = $query->execute()->fetchAll(PDO::FETCH_ASSOC); | |
return self::buildObjectArray($entries); | |
} | |
/** | |
* Given an associative array of IDs, keyed by the PK field name, return | |
* an array of objects of type $objectName | |
*/ | |
public static function buildObjectArray(array $entries) | |
{ | |
$objs = array(); | |
foreach($entries as $entry) { | |
$obj = AbstractFactory::create($entry[static::$pkField], static::$objectName); | |
if($obj){ | |
$objs[$entry[static::$pkField]] = $obj; | |
} | |
} | |
return $objs; | |
} | |
} | |
abstract class AbstractFactory | |
{ | |
public static function create($id,$type) { | |
return new $type($id); | |
} | |
} | |
abstract class ObjectFactory extends AbstractFactory | |
{ | |
public static function create($id){ | |
$type = static::$objectName; | |
if(!isset($type)){ | |
throw new Exception('Missing $objectName property in subclass'); | |
} | |
return parent::create($id, $type); | |
} | |
} | |
class DinosaurFactory extends ObjectFactory | |
{ | |
protected static $objectName = 'Dinosaur'; | |
} | |
class DinosaurCollection extends BaseCollection implements Records | |
{ | |
protected static $objectName = 'Dinosaur', | |
$tableName = 'dinosaur', | |
$tableAlias = 'd', | |
$pkField = 'did'; | |
private function __construct(){ | |
} | |
public static function get($did){ | |
return DinosaurFactory::create($id); | |
} | |
} | |
class Dinosaur extends BaseObject implements Record | |
{ | |
protected $tableName = 'dinosaur'; | |
protected $tableAlias = 'd'; | |
protected $pkField = 'did'; | |
/** | |
* Constructor | |
* @author | |
* @param Integer $did | |
*/ | |
public function __construct($did){ | |
$this->id = (int)$did; | |
$this->$pkField = (int)$did; | |
$this->load(); | |
} | |
} | |
// echo DinosaurCollection::get($did); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment