Files
scoutiq/app/Models/Model.php

153 lines
4.0 KiB
PHP

<?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]);
}
}