Skip to content

Instantly share code, notes, and snippets.

@jtarleton
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jtarleton/e86a0a7bb480be1412c4 to your computer and use it in GitHub Desktop.
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
<?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