Dragon-Knight/server/app/database.php

92 lines
1.9 KiB
PHP

<?php
/*
SQLite database wrapper class.
By default, foreign keys are enabled and the database is in WAL mode. In general
these defaults should be perfect for most use cases.
*/
class Database
{
private PDO $c;
private int $queries = 0;
private array $log = [];
private string $error = '';
private float $time = 0;
public function __construct(string $path, array $opts = [])
{
$opts = !empty($opts) ? $opts : [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$this->c = new PDO("sqlite:$path", null, null, $opts);
$this->c->exec('PRAGMA foreign_keys = ON;'); // Enable foreign keys
$this->c->exec('PRAGMA journal_mode = WAL;'); // Enable WAL
} catch (PDOException $e) {
$this->error = "Failed to open database: " . $e->getMessage();
throw $e;
}
}
public function do(string $query, array $params = []): PDOStatement|false
{
$start = microtime(true);
try {
$stmt = $this->c->prepare($query);
$stmt->execute($params);
$this->record($query, $start);
return $stmt;
} catch (PDOException $e) {
$this->error = $e->getMessage();
return false;
}
}
public function q(string $query): PDOStatement|false
{
$start = microtime(true);
try {
$stmt = $this->c->query($query);
$this->record($query, $start);
return $stmt;
} catch (PDOException $e) {
$this->error = $e->getMessage();
return false;
}
}
private function record(string $query, float $start): void
{
$time = microtime(true) - $start;
$this->queries++;
$this->log[] = [$query, $time];
$this->time += $time;
}
public function error(): string
{
return $this->error;
}
public function queries(): int
{
return $this->queries;
}
public function log(): array
{
return $this->log;
}
public function time(): float
{
return $this->time;
}
}