PaperBag/models/Model.php

211 lines
6.0 KiB
PHP

<?php
//namespace models;
define("DATABASE", Config::get('database', "database"));
abstract class Model {
protected static $database = DATABASE;
protected static $table;
protected static $tableExtends = null;
protected static $fields;
protected $isLoaded = false;
protected $initialValues = [];
protected $errors = [];
public function __construct($id = 0){
foreach (static::$fields as $field => $type){
switch ($type){
case "INT":
$this->{$field} = 0;
break;
case "VARCHAR":
case "TEXT":
default:
$this->{$field} = "";
break;
}
}
if($id > 0){
try {
$firstField = array_keys(static::$fields)[0];
$result = DB::query("SELECT `".implode("`, `", array_keys(static::$fields))."` FROM ".static::$database.".".static::$table . " t1 WHERE `$firstField` = ?", $id )->fetch_assoc();
$values = [];
foreach (static::$fields as $field => $type){
$this->{ $field } = $result[$field];
// cache initial value
$values[$field] = $this->{$field};
}
$this->isLoaded = true;
} catch (DatabaseException $e) {
$this->errors[] = $e;
}
}
$this->initialValues = $this->asArray();
}
/**
* @throws DatabaseException
*/
public static function get($filter = null){
if(!self::verify()) {
return false;
}
$fields = array_keys(static::$fields);
if(is_array( static::$tableExtends) ){
$ext = new static::$tableExtends['model']();
$fields = array_merge(
$fields,
array_keys($ext::$fields)
);
$duplicateKeys = array_intersect(array_keys(static::$fields), array_keys($ext::$fields));
foreach ($duplicateKeys as $dkey){
$fieldsKey = array_search($dkey, $fields);
$fields[$fieldsKey] = "t1`.`".$fields[$fieldsKey];
$fieldsKey = array_search($dkey, $fields);
$fields[$fieldsKey] = "t2`.`".$fields[$fieldsKey];
}
$extendSql = sprintf(
" LEFT JOIN %s.%s t2 ON t2.%s = t1.%s",
$ext::$database,
$ext::$table,
static::$tableExtends['internalKey'],
static::$tableExtends['foreignKey']
);
}
$args = array();
$sql = "SELECT `".implode("`, `", $fields)."`";
$sql .= " FROM ".static::$database.".".static::$table . " t1";
$sql .= $extendSql ?? '';
if(!empty($filter)){
$filterSql = array();
foreach ($filter as $key => $value){
if(is_array($value)){
$filterSql[] = sprintf("%s %s ?", $key, $value[0]);
$args[] = $value[1];
}
else {
$filterSql[] = "$key = ?";
$args[] = $value;
}
}
$sql .= ' WHERE '. implode(',', $filterSql);
}
// if(DEBUG){
// $q = DB::queryTest($sql, $args);
// }
// else {
$q = DB::query($sql, $args);
// }
$result = array();
while($row = $q->fetch_assoc()){
$res = new static();
$res->isLoaded = true;
/* Alternative for non-joined queries:
foreach (static::$fields as $key => $ignore){
$res->{ $key } = $row[$key];
} /* */
foreach (array_keys($row) as $col){
$res->{ $col } = $row[$col];
}
$result[] = $res;
}
return $result;
}
private static function verify(): bool {
if(is_array(static::$fields) && !empty(static::$table)){
return true;
}
return false;
}
public function isLoaded() : bool {
return $this->isLoaded;
}
// public function set($value, )
/**
* @throws DatabaseException
*/
public function save(){
$newFields = [];
$newValues = [];
$allExceptFirstFields = [];
$allExceptFirstValues = [];
$fieldCount = 0;
foreach(static::$fields as $field => $type){
$currValue = $this->{ $field };
if(!empty($this->initialValues) && $currValue != $this->initialValues[$field]){
$newFields[] = $field;
$newValues[] = $currValue;
}
if($fieldCount > 0){
$allExceptFirstFields[] = $field;
$allExceptFirstValues[] = $currValue;
}
$fieldCount++;
}
if(!empty($this->initialValues) && empty($newValues)){
return false;
}
if($this->isLoaded()){
$updateSets = [];
foreach($newFields as $field){
$updateSets[] = "`$field` = ?";
}
DB::query(sprintf('UPDATE %s.%s SET %s WHERE %s LIMIT 1', static::$database, static::$table, implode(', ', $updateSets), "`" . array_keys(static::$fields)[0] . "` = ?"), array_merge($newValues, [$this->{array_keys(static::$fields)[0]}]));
}
else {
$sql = sprintf('INSERT INTO %s.%s (%s) VALUE (%s)', static::$database, static::$table, implode(', ', $newFields), implode(', ', array_fill(0, count($newFields), '?')));
DB::query($sql, $newValues);
$insertid = DB::insert_id();
$this->{ array_keys(static::$fields)[0] } = $insertid;
$this->isLoaded = true;
return $insertid;
}
return true;
}
public function asArray(): array {
$arr = [];
foreach ($this as $key => $val){
$arr[$key] = $val;
}
return $arr;
}
}