diff options
Diffstat (limited to 'frontend/Model.php')
-rw-r--r-- | frontend/Model.php | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/frontend/Model.php b/frontend/Model.php new file mode 100644 index 0000000..0f70aa2 --- /dev/null +++ b/frontend/Model.php @@ -0,0 +1,138 @@ +<?php +class ModelNotFoundException extends Exception {} +class ModelCreateFailedException extends Exception {} +class ModelIllegalAccessException extends Exception {} +class ModelSetFailedException extends Exception {} + +abstract class Model { + public static + $table = '', + $primary_key = 'id', + $protected_columns = ['id'], + $fillable_columns = [], + $timestamps = [], + $dates = [], + $booleans = []; + + protected $pdo, $data; + + const TABLE_PREFIX = ''; + + public function __construct($pdo, $id) { + $this->pdo = $pdo; + + $stmt = $this->pdo->prepare("SELECT * FROM `".self::table()."` WHERE `".static::$primary_key."`=?"); + $stmt->execute([$id]); + if ($stmt->rowCount() == 0) { + throw new ModelNotFoundException("The ".static::$table." with id '$id' could not be found."); + } + $this->data = $stmt->fetch(PDO::FETCH_ASSOC); + } + + public function __set($key, $value) { + if (!in_array($key, static::$fillable_columns)) { + throw new ModelIllegalAccessException("Column `".self::table()."`.`$key` cannot be edited."); + } + if ($this->data[$key] == $value) { + return; + } + $stmt = $this->pdo->prepare("UPDATE `".self::table()."` SET `$key`=? WHERE `".static::$primary_key."`=?"); + $stmt->execute([ + $this->mutator($key, $value), + $this->data[static::$primary_key] + ]); + if ($stmt->rowCount() != 1) { + throw new ModelSetFailedException("Failed to update `".self::table()."`.`$key` to '$value'."); + } + $this->data[$key] = $value; + } + + public function __get($key) { + return $this->accessor($key, $this->data[$key]); + } + + public static function create($pdo, $values) { + $class = get_called_class(); + + $columns = array_combine(static::$fillable_columns, $values); + $questions = []; + + foreach ($columns as $column => $value) { + $columns[$column] = $class::mutator($column, $value); + $questions[] = '?'; + } + + $stmt = $pdo->prepare( + "INSERT INTO `".self::table()."` " . + "(`" . implode('`, `', array_keys($columns)) . "`) " . + "VALUES (" . implode(',', $questions) . ")"); + $stmt->execute(array_values($columns)); + + if ($stmt->rowCount() != 1) + throw new ModelCreateFailedException(); + + return new $class($pdo, $pdo->lastInsertId()); + } + + public static function searchIds($pdo, $where = [], $values = []) { + $stmt = $pdo->prepare("SELECT `id` FROM `".static::table()."`" . ((count($where) > 0) ? (" WHERE (" . implode(') AND (', $where) . ")") : "")); + $stmt->execute($values); + + $ids = []; + foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) { + $ids[] = $row['id']; + } + return $ids; + } + + public static function search($pdo, $where = [], $values = []) { + $class = get_called_class(); + + $items = []; + foreach (self::searchIds($pdo, $where, $values) as $id) { + $items[] = new $class($pdo, $id); + } + return $items; + } + + public static function count($pdo, $where = [], $values = []) { + $class = get_called_class(); + + $stmt = $pdo->prepare("SELECT COUNT(*) FROM `".static::table()."`" . ((count($where) > 0) ? (" WHERE (" . implode(') AND (', $where) . ")") : "")); + $stmt->execute($values); + + return $stmt->fetchColumn(); + } + + protected static function accessor($key, $value) { + if (is_null($value)) { + return null; + } elseif (in_array($key, static::$booleans)) { + return (bool) $value; + } elseif (in_array($key, static::$dates) || in_array($key, static::$timestamps)) { + return strtotime($value); + } else { + return $value; + } + } + + protected static function mutator($key, $value) { + if (in_array($key, static::$dates) && is_int($value)) { + return date('Y-m-d', $value); + } elseif (in_array($key, static::$timestamps) && is_int($value)) { + return date('Y-m-d H:i:s', $value); + } else { + return (string) $value; + } + } + + public function delete() { + $stmt = $this->pdo->prepare("DELETE FROM `".self::table()."` WHERE `".static::$primary_key."`=?"); + $stmt->execute([$this->data[static::$primary_key]]); + return $stmt->rowCount() != 0; + } + + private static function table() { + return self::TABLE_PREFIX . static::$table; + } +} |