197 lines
6.7 KiB
PHP
197 lines
6.7 KiB
PHP
<?php
|
|
|
|
class TTCrudBaseModel {
|
|
public function __construct($data = []) {
|
|
if (empty($data)) return;
|
|
foreach ($data as $field => $value) {
|
|
if (property_exists(get_called_class(), $field)) {
|
|
$this->$field = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function create($data) {
|
|
$FronkDB = FronkDB::singleton();
|
|
$db = $FronkDB->link;
|
|
$table = self::getTable();
|
|
self::checkAllFields($data, ['id']);
|
|
|
|
$sqlColumns = [];
|
|
$sqlValues = [];
|
|
foreach ($data as $field => $value) {
|
|
if (!property_exists(get_called_class(), $field)) {
|
|
die(json_encode([
|
|
"status" => "error",
|
|
"error" => "Field $field does not exist in " . get_called_class(),
|
|
"data" => $data
|
|
]));
|
|
}
|
|
|
|
if (is_array($value)) {
|
|
$value = json_encode($value);
|
|
}
|
|
|
|
$sqlValues[] = $value === null ? 'NULL' : "'" . $db->real_escape_string($value) . "'";
|
|
$sqlColumns[] = "`$field`";
|
|
}
|
|
|
|
$sql = "INSERT INTO `$table` (" . implode(", ", $sqlColumns) . ") VALUES (" . implode(", ", $sqlValues) . ")";
|
|
$db->query($sql) or die($db->error);
|
|
|
|
return $db->insert_id;
|
|
}
|
|
|
|
public static function getTable(): string {
|
|
return str_replace('Model', '', get_called_class());
|
|
}
|
|
|
|
/**
|
|
* Checks if all required fields of the current class are present in a given data array.
|
|
*
|
|
* This method uses reflection to determine which fields are required based on their type declarations.
|
|
* It then iterates over these required fields and throws an exception if any of them are missing
|
|
* from the provided data array.
|
|
*
|
|
* @param array $data The data array to check.
|
|
* @param array $skip An optional array of field names to skip during the check.
|
|
*
|
|
* @return void
|
|
* @throws Exception If any required field is missing in the `$data` array.
|
|
*
|
|
*/
|
|
public static function checkAllFields(array $data, array $skip = []) {
|
|
$requiredVars = array_filter(get_class_vars(get_called_class()), function ($value, $key) {
|
|
$reflectionProperty = new ReflectionProperty(get_called_class(), $key);
|
|
return !$reflectionProperty->hasType() || !$reflectionProperty->getType()->allowsNull();
|
|
}, ARRAY_FILTER_USE_BOTH);
|
|
|
|
foreach ($requiredVars as $field => $value) {
|
|
if (in_array($field, $skip)) {
|
|
continue;
|
|
}
|
|
|
|
if (!isset($data[$field])) {
|
|
http_response_code(500);
|
|
die(json_encode([
|
|
"status" => "error",
|
|
"error" => "Required field $field is missing in data array",
|
|
"data" => $data
|
|
]));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public static function get($id): TTCrudBaseModel {
|
|
$FronkDB = FronkDB::singleton();
|
|
$db = $FronkDB->link;
|
|
$id = $db->real_escape_string($id);
|
|
$table = self::getTable();
|
|
$sql = "SELECT * FROM `$table` WHERE `id` = $id";
|
|
|
|
$result = $db->query($sql);
|
|
// as TTCRudBaseModel is abstract, we need to get the class name of the child class
|
|
$class = get_called_class();
|
|
return new $class($result->fetch_assoc());
|
|
}
|
|
|
|
public static function count($filter = []): int {
|
|
$FronkDB = FronkDB::singleton();
|
|
$db = $FronkDB->link;
|
|
$table = self::getTable();
|
|
$filter = self::getSQLFilter($filter);
|
|
$sql = "SELECT COUNT(*) as count FROM `$table` $filter";
|
|
$result = $db->query($sql);
|
|
|
|
return $result->fetch_assoc()['count'];
|
|
}
|
|
|
|
public static function getSQLFilter(array $filter): string {
|
|
if (empty($filter)) return '';
|
|
$sql = 'WHERE 1=1';
|
|
$calledClass = get_called_class();
|
|
|
|
foreach ($filter as $key => $value) {
|
|
foreach (explode('|', $key) as $column) {
|
|
if (!property_exists($calledClass, $column)) {
|
|
throw new InvalidArgumentException("Field $column does not exist in $calledClass");
|
|
}
|
|
}
|
|
$sql .= Helper::generateFilterCondition($value, $key, gettype($value) === "integer");
|
|
}
|
|
|
|
return $sql;
|
|
}
|
|
|
|
public static function getAll($filter = [], $limit = null, $offset = 0, $order = ["key" => null]): array {
|
|
$FronkDB = FronkDB::singleton();
|
|
$db = $FronkDB->link;
|
|
$table = self::getTable();
|
|
$filter = self::getSQLFilter($filter);
|
|
$sql = "SELECT * FROM `$table` $filter";
|
|
|
|
$sql .= $order['key'] === null ? " ORDER BY `id` ASC" : " ORDER BY `" . $order['key'] . "` " . $order['order'];
|
|
$sql .= $limit === null ? "" : " LIMIT " . $limit . " OFFSET " . $offset;
|
|
try {
|
|
$result = $db->query($sql);
|
|
} catch (Exception $e) {
|
|
echo $sql;
|
|
die($e->getMessage());
|
|
}
|
|
|
|
$rows = [];
|
|
$class = get_called_class();
|
|
while ($row = $result->fetch_assoc()) {
|
|
$rows[] = new $class($row);
|
|
}
|
|
|
|
return $rows;
|
|
}
|
|
|
|
public static function update($data) {
|
|
$FronkDB = FronkDB::singleton();
|
|
$db = $FronkDB->link;
|
|
$table = self::getTable();
|
|
|
|
// Check if all fields are set
|
|
self::checkAllFields($data);
|
|
|
|
$values = [];
|
|
foreach ($data as $field => $value) {
|
|
if (!property_exists(get_called_class(), $field)) {
|
|
throw new Exception("Field $field does not exist in " . get_called_class());
|
|
}
|
|
if ($field === "id") {
|
|
continue;
|
|
}
|
|
// TODO: make this cleaner
|
|
if ($value === "" && (new ReflectionProperty(get_called_class(), $field))->getType()->getName() === "float") {
|
|
$value = null;
|
|
}
|
|
if ($value === "" && (new ReflectionProperty(get_called_class(), $field))->getType()->getName() === "int") {
|
|
$value = null;
|
|
}
|
|
|
|
if (is_array($value)) {
|
|
$value = json_encode($value);
|
|
}
|
|
|
|
$values[] = $value === null ? "`$field` = NULL" : "`$field` = '" . $db->real_escape_string($value) . "'";
|
|
}
|
|
|
|
$sql = "UPDATE `$table` SET " . implode(", ", $values) . " WHERE `id` = " . $db->real_escape_string($data['id']);
|
|
$db->query($sql);
|
|
return $db->affected_rows;
|
|
}
|
|
|
|
public static function delete($id) {
|
|
$FronkDB = FronkDB::singleton();
|
|
$db = $FronkDB->link;
|
|
$table = self::getTable();
|
|
$id = $db->real_escape_string($id);
|
|
$sql = "DELETE FROM `$table` WHERE `id` = $id";
|
|
$db->query($sql);
|
|
return $db->affected_rows;
|
|
}
|
|
|
|
} |