Complete Phase 1: MVC, DB migrations, Auth, RBAC, Security, and Views
This commit is contained in:
152
app/Models/Model.php
Normal file
152
app/Models/Model.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Core\App;
|
||||
use App\Services\Database\Connection;
|
||||
use PDO;
|
||||
|
||||
abstract class Model
|
||||
{
|
||||
protected static ?PDO $db = null;
|
||||
protected string $table;
|
||||
protected string $primaryKey = 'id';
|
||||
protected array $attributes = [];
|
||||
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
if (self::$db === null && isset(App::$app)) {
|
||||
$connection = App::$app->container->get(Connection::class);
|
||||
self::$db = $connection->getPdo();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active database connection.
|
||||
*/
|
||||
public static function getDb(): PDO
|
||||
{
|
||||
if (self::$db === null) {
|
||||
$connection = App::$app->container->get(Connection::class);
|
||||
self::$db = $connection->getPdo();
|
||||
}
|
||||
return self::$db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter for attributes.
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
return $this->attributes[$name] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic setter for attributes.
|
||||
*/
|
||||
public function __set(string $name, $value): void
|
||||
{
|
||||
$this->attributes[$name] = $value;
|
||||
}
|
||||
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a record by ID.
|
||||
*/
|
||||
public static function find(int|string $id): ?static
|
||||
{
|
||||
$instance = new static();
|
||||
$db = self::getDb();
|
||||
|
||||
$sql = "SELECT * FROM {$instance->table} WHERE {$instance->primaryKey} = :id AND deleted_at IS NULL LIMIT 1";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute(['id' => $id]);
|
||||
|
||||
$data = $stmt->fetch();
|
||||
if (!$data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new static($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all active records.
|
||||
*/
|
||||
public static function all(): array
|
||||
{
|
||||
$instance = new static();
|
||||
$db = self::getDb();
|
||||
|
||||
$sql = "SELECT * FROM {$instance->table} WHERE deleted_at IS NULL";
|
||||
$stmt = $db->query($sql);
|
||||
|
||||
$results = [];
|
||||
while ($row = $stmt->fetch()) {
|
||||
$results[] = new static($row);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the active record (INSERT or UPDATE).
|
||||
*/
|
||||
public function save(): bool
|
||||
{
|
||||
$db = self::getDb();
|
||||
$id = $this->attributes[$this->primaryKey] ?? null;
|
||||
|
||||
if ($id) {
|
||||
// Update flow
|
||||
$fields = [];
|
||||
$params = [];
|
||||
foreach ($this->attributes as $key => $value) {
|
||||
if ($key === $this->primaryKey || $key === 'created_at' || $key === 'updated_at') {
|
||||
continue;
|
||||
}
|
||||
$fields[] = "`{$key}` = :{$key}";
|
||||
$params[$key] = $value;
|
||||
}
|
||||
$params[$this->primaryKey] = $id;
|
||||
|
||||
$sql = "UPDATE `{$this->table}` SET " . implode(', ', $fields) . " WHERE `{$this->primaryKey}` = :{$this->primaryKey}";
|
||||
$stmt = $db->prepare($sql);
|
||||
return $stmt->execute($params);
|
||||
} else {
|
||||
// Insert flow
|
||||
$keys = array_keys($this->attributes);
|
||||
$placeholders = array_map(fn($key) => ":{$key}", $keys);
|
||||
|
||||
$sql = "INSERT INTO `{$this->table}` (" . implode(', ', array_map(fn($k) => "`{$k}`", $keys)) . ") VALUES (" . implode(', ', $placeholders) . ")";
|
||||
$stmt = $db->prepare($sql);
|
||||
$success = $stmt->execute($this->attributes);
|
||||
|
||||
if ($success) {
|
||||
$this->attributes[$this->primaryKey] = (int)$db->lastInsertId();
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft delete active record.
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
$db = self::getDb();
|
||||
$id = $this->attributes[$this->primaryKey] ?? null;
|
||||
if (!$id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql = "UPDATE `{$this->table}` SET deleted_at = NOW() WHERE `{$this->primaryKey}` = :id";
|
||||
$stmt = $db->prepare($sql);
|
||||
return $stmt->execute(['id' => $id]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user