From 32e12ff7f86c6eab5b8295e19fa5d18826dfdb16 Mon Sep 17 00:00:00 2001 From: Camil Staps Date: Wed, 27 Jul 2016 16:17:32 +0200 Subject: Initial Model class --- classes/Model.php | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 classes/Model.php (limited to 'classes') diff --git a/classes/Model.php b/classes/Model.php new file mode 100644 index 0000000..37c719a --- /dev/null +++ b/classes/Model.php @@ -0,0 +1,145 @@ +. + */ + +/** + * Thrown in Model when a table row could not be found + */ +class ModelNotFoundException extends Exception { +} + +/** + * Thrown in Model when a column cannot be edited + */ +class ModelIllegalAccessException extends Exception { +} + +/** + * An abstract interface to a database table + */ +abstract class Model { + /** + * @var string $table The database table + * @var string[] $protected_columns Columns that cannot be edited + * @var string[] $fillable_columns Columns that can be edited + * @var string $primary_key The table's primary key + */ + public + $table = '', + $protected_columns = ['id'], + $fillable_columns = [], + $primary_key = 'id'; + + /** + * @var PDO $pdo A PDO instance for database communication + * @var mixed[] $data The column values + */ + protected $pdo, $data; + + public function __construct($pdo, $id) { + $this->pdo = $pdo; + + $stmt = $this->pdo->prepare("SELECT * FROM `".$this->table()."` WHERE `{$this->primary_key}`=?"); + $stmt->execute([$id]); + if ($stmt->rowCount() == 0) { + throw new Exception("The {$this->table} with id '$id' could not be found."); + } + $this->data = $stmt->fetch(PDO::FETCH_ASSOC); + } + + /** + * Set a column value + * + * @param string $key The column + * @param mixed $value The value + * + * @throws PDOException Database error + * + * @return bool True iff the value has been changed + */ + public function __set($key, $value) { + if (!in_array($key, $this->fillable_columns)) { + throw new ModelIllegalAccessException("Column $key cannot be edited."); + } + $stmt = $this->pdo->prepare("UPDATE `".$this->table()."` SET `$key`=? WHERE `{$this->primary_key}`=?"); + $stmt->execute([$this->mutator($value), $this->data[$this->primary_key]]); + $this->data[$key] = $value; + return $this->rowCount() != 0; + } + + /** + * Get a column value + * + * @param string $key The column + * + * @return mixed The value + */ + public function __get($key) { + return $this->accessor($key, $this->data[$key]); + } + + /** + * Post-__get() hook to modify the value + * + * @param string $key The column + * @param string $value The value + * + * @return string The modified value (default: $value) + */ + protected function accessor($key, $value) { + return $value; + } + + /** + * Pre-__set() hook to modify a value + * + * @param string $key The column + * @param mixed $value The value + * + * @return string The modified value (default: $value casted to string) + */ + protected function mutator($key, $value) { + return (string) $value; + } + + /** + * Delete the row + * + * @throws PDOException Database error + * + * @return bool True iff the row was really deleted + */ + public function delete() { + $stmt = $this->pdo->prepare("DELETE FROM `{$this->table()}` WHERE `{$this->primary_key}`=?"); + $stmt->execute([$this->data[$this->primary_key]]); + return $stmt->rowCount() != 0; + } + + /** + * The actual table, after adding prefixes and the like + * + * @return string The database table + */ + private function table() { + return constants::db_prefix . $this->table; + } +} -- cgit v1.2.3