Last active
December 16, 2020 03:52
-
-
Save kiurchv/5555313 to your computer and use it in GitHub Desktop.
ORM implementation
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 | |
/** | |
* ORM implementation. | |
* | |
* BaseModel realizes all logic for managing database connections and | |
* work with entities which stored in database as plain PHP objects. | |
* | |
* This implementation supports object relations: | |
* | |
* * one to one | |
* * many to one | |
* | |
* Not realized: | |
* | |
* * model validations(use database constraints) | |
* * many to many object relation | |
* | |
* @author Miroslav Kyurchev <[email protected]> | |
* @copyright 2013 Miroslav Kyurchev | |
* @depends Inflector | |
* @license MIT | |
* @since 0.1 | |
* @version 0.1 | |
*/ | |
class BaseModel | |
{ | |
private static $db; | |
protected $attributes = array(); | |
/** | |
* Connects to database. | |
* | |
* @access public | |
* @static | |
* @return PDO Object representing a connection to a database | |
*/ | |
static function db() | |
{ | |
if (!isset(self::$db)) { | |
if (isset($_ENV["DATABASE_URL"])) { | |
extract(parse_url($_ENV["DATABASE_URL"])); | |
$dsn = "pgsql:host=$host;dbname=".substr($path, 1).";user=$user;password=$pass"; | |
} else { | |
$dsn = "pgsql:host=localhost;dbname=wt_lab2_test;user=postgres;password=postgres"; | |
} | |
self::$db = new PDO($dsn); | |
} | |
return self::$db; | |
} | |
/** | |
* Returns name of table corresponding current model. | |
* @access public | |
* @static | |
* @return string Name of the table corresponding current model | |
*/ | |
static function table_name() | |
{ | |
return Inflector::tableize(get_called_class()); | |
} | |
/** | |
* Gets all records. | |
* @access public | |
* @static | |
* @return array Objects corresponiding table records | |
*/ | |
static function all() | |
{ | |
$query = 'SELECT * FROM '.self::table_name(); | |
$reflection = new ReflectionClass(get_called_class()); | |
$sth = self::db()->prepare($query); | |
$sth->setFetchMode(PDO::FETCH_INTO, $reflection->newInstance()); | |
$sth->execute(); | |
return $sth->fetchAll(PDO::FETCH_INTO); | |
} | |
/** | |
* Finds record by given column. | |
* @access public | |
* @static | |
* @param int $name Name of column to find by | |
* @param int $value Column value to find | |
* @return object Object corresponding record with given id | |
*/ | |
static function find_by($name, $value) | |
{ | |
$query = 'SELECT * FROM '.self::table_name().' WHERE '.$name.'=?'; | |
$reflection = new ReflectionClass(get_called_class()); | |
$sth = self::db()->prepare($query); | |
$sth->setFetchMode(PDO::FETCH_INTO, $reflection->newInstance()); | |
$sth->execute(array($value)); | |
return $sth->fetch(PDO::FETCH_INTO); | |
} | |
/** | |
* Finds record by id. | |
* @access public | |
* @static | |
* @param int $id Id of record to find | |
* @return object Object corresponding record with given id | |
*/ | |
static function find($id) | |
{ | |
return self::find_by('id', $id); | |
} | |
/** | |
* Constructs object and saves it to database. | |
* @access public | |
* @static | |
* @param array $attributes Attributes to save in databse | |
* @return object Object corresponding database record | |
*/ | |
static function create($attributes) | |
{ | |
$attributes = array_filter($attributes); | |
unset($attributes['id']); | |
$columns = array_keys($attributes); | |
$placeholders = array_map(function ($elem) { | |
return ":$elem"; | |
}, $columns); | |
$query = 'INSERT INTO '.self::table_name().' ('.join(', ', $columns).') values ('.join(', ', $placeholders).')'; | |
$sth = self::db()->prepare($query); | |
if ($sth->execute($attributes)) | |
{ | |
$reflection = new ReflectionClass(get_called_class()); | |
return $reflection->newInstance($attributes); | |
} else { | |
return false; | |
} | |
} | |
/** | |
* Deletes record with given id from table | |
* @access public | |
* @static | |
* @param int $id Id of record to delete | |
* @return bool Result of executing query | |
*/ | |
static function delete($id) | |
{ | |
$query = 'DELETE FROM '.self::table_name().' WHERE id=?'; | |
$sth = self::db()->prepare($query); | |
return $sth->execute(array($id)); | |
} | |
/** | |
* Finds all objects of the given model which are associated with current | |
* @access public | |
* @param string $class_name Name of the model to find | |
* @return array Objects which are associated with current | |
*/ | |
function find_assoc($class_name) | |
{ | |
$table_name = Inflector::tableize($class_name); | |
$column_name = Inflector::underscore(get_called_class()); | |
$query = 'SELECT * FROM '.$table_name.' WHERE '.$column_name.'_id=?'; | |
$reflection = new ReflectionClass($class_name); | |
$sth = self::db()->prepare($query); | |
$sth->setFetchMode(PDO::FETCH_INTO, $reflection->newInstance()); | |
$sth->execute(array($this->attributes['id'])); | |
return $sth->fetchAll(PDO::FETCH_INTO); | |
} | |
/** | |
* Updates specified attributes of object in database | |
* @access public | |
* @param array $attributes Attributes to update | |
* @return bool Result of executing query | |
*/ | |
function update($attributes) | |
{ | |
$attributes = array_filter($attributes); | |
$attributes['id'] = $this->attributes['id']; | |
$columns = array_keys($attributes); | |
$columns = array_diff($columns, array('id')); | |
$columns = array_map(function ($elem) { | |
return "$elem=:$elem"; | |
}, $columns); | |
$query = 'UPDATE '.self::table_name().' SET '.join(', ', $columns).' WHERE id=:id'; | |
$sth = self::db()->prepare($query); | |
return $sth->execute($attributes); | |
} | |
/** | |
* Saves new object to database or updates existing | |
* @access public | |
* @return mixed Object corresponding database record or result of executing query | |
*/ | |
function save() | |
{ | |
if ((!isset($this->attributes['id']) && count($this->attributes) > 0) || count($this->attributes) > 1) { | |
if (isset($this->attributes['id'])) | |
{ | |
return $this->update($this->attributes); | |
} else { | |
return self::create($this->attributes); | |
} | |
} else { | |
trigger_error('Not specified attributes to save', E_USER_NOTICE); | |
} | |
} | |
/** | |
* Sets object properties as elements of attributes array | |
* @param string $name Name of property | |
* @param mixed $value Value of property | |
* @return void | |
*/ | |
function __set($name, $value) | |
{ | |
$this->attributes[$name] = $value; | |
} | |
/** | |
* Gets object's attributes or associated objects | |
* @param string $name Name of property | |
* @return mixed Value of property or associated objects | |
*/ | |
function __get($name) | |
{ | |
if (array_key_exists($name, $this->attributes)) { | |
return $this->attributes[$name]; | |
} elseif (array_key_exists($name.'_id', $this->attributes)) { | |
$class = Inflector::classify($name); | |
return $class::find($this->attributes[$name.'_id']); | |
} else { | |
$class = Inflector::classify($name); | |
$result = $this->find_assoc($class); | |
if (!empty($result)) { | |
return $result; | |
} else { | |
$trace = debug_backtrace(); | |
trigger_error('No objects associated or undefined attribute '.$name.' in '.$trace[0]['file'].' on line ' . $trace[0]['line'], E_USER_NOTICE); | |
return null; | |
} | |
} | |
} | |
/** | |
* Initializes object | |
* @param array $attributes Attributes to save in databse | |
* @return void | |
*/ | |
function __construct($attributes = array()) | |
{ | |
$this->attributes = $attributes; | |
} | |
/** | |
* Deletes corresponding record from database | |
* @access public | |
* @return bool Result of executing query | |
*/ | |
function destroy() { | |
if (isset($this->attributes['id'])) | |
self::delete($this->attributes['id']); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment