Skip to content

Instantly share code, notes, and snippets.

@NuckChorris
Created April 24, 2015 09:51
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 NuckChorris/e74a747b426e6ab68a2e to your computer and use it in GitHub Desktop.
Save NuckChorris/e74a747b426e6ab68a2e to your computer and use it in GitHub Desktop.
<?php
include_once 'classes/db.class.php';
/**
* This is an ORM.
* I may have gone a bit overboard on this final project.
* I just got tired of constantly dropping into raw SQL for mundane crap.
*/
class Model {
private $_attributes = array();
private $_associations_unloaded = array();
protected $_new = false;
/**
* Dynamically save/retrieve properties, casting to the desired type
*/
public function __set($key, $val) {
if (array_key_exists($key, $this->_fields)) {
// Property set
$type = $this->_fields[$key];
if (ctype_lower($type)) {
// Primitive cast
$cast_value = $val;
settype($cast_value, $type);
$this->_attributes[$key] = $cast_value;
} else {
// Class cast
$this->_attributes[$key] = new $type($val);
}
} else if (substr($key, -3) === '_id') {
// Association set
$this->_associations_unloaded[substr($key, 0, -3)] = $val;
}
}
public function __get($key) {
if (array_key_exists($key, $this->_fields)) {
return $this->_attributes[$key];
} else if (array_key_exists($key, $this->_associations)) {
$class = $this->_associations[$key][1];
if ($this->_assocations[$key][0] === 'has_one') {
return $class::find($this->_associations_unloaded[$key])[0];
} else if ($this->_associations[$key][0] === 'has_many') {
$foreign_key = substr(self::getTable(), 0, -1) . '_id';
return $class::where(array($foreign_key => $this->_attributes['id']));
}
}
}
/**
* Turn class name into a snake_case table name
*/
public static function getTable() {
$class = get_called_class();
return ltrim(strtolower(preg_replace('/[A-Z]/', '_$0', $class)), '_') . 's';
}
/**
* Get instance or instances by their ID(s)
*/
public static function find($id) {
$db = DB::conn();
$table = self::getTable();
$query = null;
if (is_array($id)) {
$ids = implode(',', $id);
$query = $db->prepare("SELECT * FROM $table WHERE id IN ($ids)");
} else {
$query = $db->prepare("SELECT * FROM $table WHERE id = :id");
$query->bindValue('id', $id, PDO::PARAM_INT);
}
$query->execute();
$query->setFetchMode(PDO::FETCH_CLASS, get_called_class());
$results = $query->fetchAll();
return is_array($id) ? $results : $results[0];
}
/**
* Get instances by a field or set of fields
*/
public static function where($arr) {
$db = DB::conn();
$table = self::getTable();
$query = "SELECT * FROM $table WHERE ";
foreach (array_keys($arr) as $column) {
$query .= "$column = :$column AND";
}
// Chop off the final AND
$query = substr($query, 0, -4);
$query = $db->prepare($query);
foreach ($arr as $col => $val) {
$query->bindValue($col, $val);
}
$query->execute();
$query->setFetchMode(PDO::FETCH_CLASS, get_called_class());
return $query->fetchAll();
}
/**
* Save the instance
*/
public function save() {
$db = DB::conn();
$keys = array_keys($this->_attributes);
$table = self::getTable();
if ($this->_new) {
$columns = implode(',', $keys);
$placeholders = ':' . implode(',:', $keys);
$query = $db->prepare("INSERT INTO $table ($columns) VALUES ($placeholders)");
} else {
$query = "UPDATE $table SET ";
foreach ($keys as $column) {
if ($column !== 'id') {
$query .= "$column=:$column,";
}
}
$query = substr($query, 0, -1);
$query .= " WHERE id = :id";
}
$query = $db->prepare($query);
foreach($this->_attributes as $attr => $value) {
// Because DateTime doesn't implement __toString for some stupid reason
if (is_a($value, 'DateTime')) {
$value = $value->format('Y-m-d H:i:s');
}
$query->bindValue($attr, $value);
}
return $query->execute();
}
public function fields() {
return array_keys($this->_fields);
}
/**
* Create an unsaved instance
*/
public static function create() {
$class = get_called_class();
$new = new $class();
$new->_new = true;
return $new;
}
/**
* Run validators
*/
public function isValid() {
$errors = array();
foreach($this->fields() as $field) {
$validator = 'validate_' . $field;
if (method_exists($this, $validator)) {
$err = call_user_func(array($this, $validator), $this->_attributes[$field]);
if ($err) {
$errors[$field] = $err;
}
}
}
if (count($errors) > 0) {
return $errors;
} else {
return true;
}
}
}
?>
<?php
include_once '_model.class.php';
include_once 'status_report.class.php';
class Incident extends Model {
protected $_fields = array(
'id' => 'integer',
'title' => 'string',
'created_at' => 'DateTime',
'updated_at' => 'DateTime',
'status' => 'string',
'command_post' => 'string'
);
protected $_associations = array(
'status_reports' => array('has_many', 'StatusReport')
);
}
?>
<?php
include_once '_model.class.php';
include_once 'user.class.php';
include_once 'incident.class.php';
class Role extends Model {
protected $_fields = array(
'id' => 'integer',
'role' => 'string',
'other_role' => 'string',
'sign_on' => 'DateTime',
'sign_off' => 'DateTime'
);
protected $_associations = array(
'user' => array('has_one', 'User'),
'incident' => array('has_one', 'Incident')
);
}
?>
<?php
include_once '_model.class.php';
include_once 'user.class.php';
include_once 'incident.class.php';
class StatusReport extends Model {
protected $_fields = array(
'id' => 'integer',
'created_at' => 'DateTime',
'title' => 'string',
'text' => 'string'
);
protected $_associations = array(
'user' => array('has_one', 'User'),
'incident' => array('has_one', 'Incident'),
);
}
?>
<?php
include_once '_model.class.php';
class User extends Model {
protected $_fields = array(
'id' => 'integer',
'email' => 'string',
'password' => 'string',
'first_name' => 'string',
'last_name' => 'string',
'administrator' => 'boolean'
);
protected $_associations = array(
'role' => array('has_many', 'Role')
);
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment