257 lines
5.3 KiB
PHP
257 lines
5.3 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Core\Database;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* NovaCore Base Model
|
||
|
|
* Base model class for database operations
|
||
|
|
*/
|
||
|
|
abstract class Model
|
||
|
|
{
|
||
|
|
protected Connection $connection;
|
||
|
|
protected string $table;
|
||
|
|
protected string $primaryKey = 'id';
|
||
|
|
protected array $fillable = [];
|
||
|
|
protected array $guarded = [];
|
||
|
|
protected array $attributes = [];
|
||
|
|
protected bool $timestamps = true;
|
||
|
|
protected string $createdAt = 'created_at';
|
||
|
|
protected string $updatedAt = 'updated_at';
|
||
|
|
|
||
|
|
public function __construct(array $attributes = [])
|
||
|
|
{
|
||
|
|
$this->attributes = $attributes;
|
||
|
|
$this->connection = $this->getConnection();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get database connection
|
||
|
|
*/
|
||
|
|
protected function getConnection(): Connection
|
||
|
|
{
|
||
|
|
$config = include __DIR__ . '/../../Config/database.php';
|
||
|
|
$connectionConfig = $config['connections'][$config['default']];
|
||
|
|
|
||
|
|
return new Connection($connectionConfig);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get query builder instance
|
||
|
|
*/
|
||
|
|
protected function newQuery(): QueryBuilder
|
||
|
|
{
|
||
|
|
return new QueryBuilder($this->connection, $this->table);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Find record by ID
|
||
|
|
*/
|
||
|
|
public static function find(int $id): ?self
|
||
|
|
{
|
||
|
|
$instance = new static();
|
||
|
|
$result = $instance->newQuery()->where($instance->primaryKey, $id)->first();
|
||
|
|
|
||
|
|
if (!$result) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
return new static($result);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Find all records
|
||
|
|
*/
|
||
|
|
public static function all(): array
|
||
|
|
{
|
||
|
|
$instance = new static();
|
||
|
|
$results = $instance->newQuery()->get();
|
||
|
|
|
||
|
|
return array_map(function ($attributes) {
|
||
|
|
return new static($attributes);
|
||
|
|
}, $results);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Create new record
|
||
|
|
*/
|
||
|
|
public static function create(array $attributes): self
|
||
|
|
{
|
||
|
|
$instance = new static();
|
||
|
|
$instance->fill($attributes);
|
||
|
|
$instance->save();
|
||
|
|
|
||
|
|
return $instance;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fill model attributes
|
||
|
|
*/
|
||
|
|
public function fill(array $attributes): self
|
||
|
|
{
|
||
|
|
foreach ($attributes as $key => $value) {
|
||
|
|
if ($this->isFillable($key)) {
|
||
|
|
$this->attributes[$key] = $value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if attribute is fillable
|
||
|
|
*/
|
||
|
|
protected function isFillable(string $key): bool
|
||
|
|
{
|
||
|
|
if (in_array($key, $this->guarded)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (empty($this->fillable)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return in_array($key, $this->fillable);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Save model to database
|
||
|
|
*/
|
||
|
|
public function save(): bool
|
||
|
|
{
|
||
|
|
if ($this->exists()) {
|
||
|
|
return $this->update();
|
||
|
|
} else {
|
||
|
|
return $this->insert();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if model exists in database
|
||
|
|
*/
|
||
|
|
public function exists(): bool
|
||
|
|
{
|
||
|
|
return isset($this->attributes[$this->primaryKey]) && $this->attributes[$this->primaryKey] !== null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Insert new record
|
||
|
|
*/
|
||
|
|
protected function insert(): bool
|
||
|
|
{
|
||
|
|
$attributes = $this->attributes;
|
||
|
|
|
||
|
|
if ($this->timestamps) {
|
||
|
|
$now = date('Y-m-d H:i:s');
|
||
|
|
$attributes[$this->createdAt] = $now;
|
||
|
|
$attributes[$this->updatedAt] = $now;
|
||
|
|
}
|
||
|
|
|
||
|
|
$result = $this->newQuery()->insert($attributes);
|
||
|
|
|
||
|
|
if ($result) {
|
||
|
|
$this->attributes[$this->primaryKey] = $this->connection->lastInsertId();
|
||
|
|
}
|
||
|
|
|
||
|
|
return $result > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Update existing record
|
||
|
|
*/
|
||
|
|
protected function update(): bool
|
||
|
|
{
|
||
|
|
$attributes = $this->attributes;
|
||
|
|
unset($attributes[$this->primaryKey]);
|
||
|
|
|
||
|
|
if ($this->timestamps) {
|
||
|
|
$attributes[$this->updatedAt] = date('Y-m-d H:i:s');
|
||
|
|
}
|
||
|
|
|
||
|
|
$result = $this->newQuery()
|
||
|
|
->where($this->primaryKey, $this->attributes[$this->primaryKey])
|
||
|
|
->update($attributes);
|
||
|
|
|
||
|
|
return $result > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Delete record
|
||
|
|
*/
|
||
|
|
public function delete(): bool
|
||
|
|
{
|
||
|
|
if (!$this->exists()) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
$result = $this->newQuery()
|
||
|
|
->where($this->primaryKey, $this->attributes[$this->primaryKey])
|
||
|
|
->delete();
|
||
|
|
|
||
|
|
return $result > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get attribute value
|
||
|
|
*/
|
||
|
|
public function __get(string $key)
|
||
|
|
{
|
||
|
|
return $this->attributes[$key] ?? null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set attribute value
|
||
|
|
*/
|
||
|
|
public function __set(string $key, $value): void
|
||
|
|
{
|
||
|
|
$this->attributes[$key] = $value;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if attribute exists
|
||
|
|
*/
|
||
|
|
public function __isset(string $key): bool
|
||
|
|
{
|
||
|
|
return isset($this->attributes[$key]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Convert model to array
|
||
|
|
*/
|
||
|
|
public function toArray(): array
|
||
|
|
{
|
||
|
|
return $this->attributes;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Convert model to JSON
|
||
|
|
*/
|
||
|
|
public function toJson(): string
|
||
|
|
{
|
||
|
|
return json_encode($this->attributes);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get table name
|
||
|
|
*/
|
||
|
|
public function getTable(): string
|
||
|
|
{
|
||
|
|
return $this->table;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get primary key
|
||
|
|
*/
|
||
|
|
public function getKeyName(): string
|
||
|
|
{
|
||
|
|
return $this->primaryKey;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get primary key value
|
||
|
|
*/
|
||
|
|
public function getKey()
|
||
|
|
{
|
||
|
|
return $this->attributes[$this->primaryKey] ?? null;
|
||
|
|
}
|
||
|
|
}
|