aboutsummaryrefslogtreecommitdiff
path: root/classes
diff options
context:
space:
mode:
authorCamil Staps2016-07-27 16:17:32 +0200
committerCamil Staps2016-07-27 16:17:32 +0200
commit32e12ff7f86c6eab5b8295e19fa5d18826dfdb16 (patch)
treeb3f7efb6107279a9d6436d17b27915556b642c56 /classes
parentEdit contact languages (diff)
Initial Model class
Diffstat (limited to 'classes')
-rw-r--r--classes/Model.php145
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;
+ }
+}