diff options
author | Camil Staps | 2016-07-27 16:17:32 +0200 |
---|---|---|
committer | Camil Staps | 2016-07-27 16:17:32 +0200 |
commit | 32e12ff7f86c6eab5b8295e19fa5d18826dfdb16 (patch) | |
tree | b3f7efb6107279a9d6436d17b27915556b642c56 /classes | |
parent | Edit contact languages (diff) |
Initial Model class
Diffstat (limited to 'classes')
-rw-r--r-- | classes/Model.php | 145 |
1 files changed, 145 insertions, 0 deletions
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 @@ +<?php +/** + * Provides the model class, an abstract interface to a database table + * + * @author Camil Staps + * + * BusinessAdmin: administrative software for small companies + * Copyright (C) 2015 Camil Staps (ViviSoft) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * 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; + } +} |