Compare commits
No commits in common. "2683a5b4bb20f0cb4fe7fa4fb1e70a91c1e3933c" and "22522488d89190d423a21829191f35675a40c37d" have entirely different histories.
2683a5b4bb
...
22522488d8
|
@ -1,19 +1,6 @@
|
||||||
<?php // index.php :: Primary program script, evil alien overlord, you decide.
|
<?php // index.php :: Primary program script, evil alien overlord, you decide.
|
||||||
|
|
||||||
// define our server path and bootstrap the request
|
|
||||||
const SERVER = '../server';
|
const SERVER = '../server';
|
||||||
require_once SERVER.'/bootstrap.php';
|
require_once SERVER.'/bootstrap.php';
|
||||||
|
|
||||||
// check if the server has been installed
|
if (!installed()) redirect('/install');
|
||||||
if (!installed()) redirect('/install');
|
|
||||||
|
|
||||||
// spin up our app container
|
|
||||||
$app = new App(DB);
|
|
||||||
|
|
||||||
// route the request
|
|
||||||
// routing follows a simple rule; the first segment of the URI is the
|
|
||||||
// module, and the module handles the rest
|
|
||||||
$route = App::$req->uri(0);
|
|
||||||
$routes = [
|
|
||||||
'home' => 'HomeModule::home',
|
|
||||||
];
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
The app container exists to be a dependency container for the game.
|
|
||||||
*/
|
|
||||||
|
|
||||||
class App
|
|
||||||
{
|
|
||||||
public static Database $db;
|
|
||||||
public static Request $req;
|
|
||||||
|
|
||||||
public function __construct(string $dbPath)
|
|
||||||
{
|
|
||||||
self::$req = new Request(); // the current request
|
|
||||||
self::$db = new Database($dbPath); // the database
|
|
||||||
}
|
|
||||||
|
|
||||||
public function route(string $uri, array $routes)
|
|
||||||
{
|
|
||||||
// check if the module exists
|
|
||||||
if (isset($routes[$module])) {
|
|
||||||
// if the module exists, call the module's handle method
|
|
||||||
$routes[$module]($this);
|
|
||||||
} else {
|
|
||||||
// if the module does not exist, render a 404 page
|
|
||||||
$this->render('404', [
|
|
||||||
'title' => '404',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
<?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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
class Request
|
|
||||||
{
|
|
||||||
public array $uri;
|
|
||||||
public string $method;
|
|
||||||
public array $headers;
|
|
||||||
public int $status;
|
|
||||||
|
|
||||||
public bool $htmx;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
// Get the URI and trim slashes, then break it into pieces
|
|
||||||
$uri = parse_url($_SERVER['REQUEST_URI'])['path'];
|
|
||||||
$uri = '/'.trim(trim($uri), '/');
|
|
||||||
$this->uri = explode('/', $uri);
|
|
||||||
array_shift($this->uri);
|
|
||||||
|
|
||||||
// Get the request method
|
|
||||||
$this->method = $_SERVER['REQUEST_METHOD'];
|
|
||||||
|
|
||||||
// Get all headers
|
|
||||||
$this->headers = $this->getAllHeaders();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function uri(int $index): string|false
|
|
||||||
{
|
|
||||||
if ($index == 0 && empty($this->uri[0])) return '/';
|
|
||||||
return $this->uri[$index] ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getAllHeaders(): array
|
|
||||||
{
|
|
||||||
$headers = [];
|
|
||||||
foreach ($_SERVER as $k => $v) {
|
|
||||||
if (substr($k, 0, 5) == 'HTTP_') {
|
|
||||||
$headers[str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($k, 5)))))] = $v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $headers;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +1,15 @@
|
||||||
<?php
|
<?php // bootstrap.php :: Initialize all our boring stuff
|
||||||
|
|
||||||
// @todo use a flag for this
|
|
||||||
ini_set('display_errors', 'on');
|
ini_set('display_errors', 'on');
|
||||||
error_reporting(E_ALL | E_STRICT);
|
error_reporting(E_ALL | E_STRICT);
|
||||||
|
|
||||||
define('START', microtime(true)); // start the timer for this execution
|
$start = microtime(true);
|
||||||
|
|
||||||
session_start(); // initialize the session engine
|
session_start();
|
||||||
|
|
||||||
// @todo move these to a settings config somewhere
|
|
||||||
const VERSION = '1.1.11';
|
const VERSION = '1.1.11';
|
||||||
const BUILD = '';
|
const BUILD = '';
|
||||||
const DB = SERVER.'/database/dragon.db';
|
const DB = SERVER.'/database/dragon.db';
|
||||||
|
|
||||||
require_once SERVER.'/library.php'; // include our miscellaneous functions
|
require_once SERVER.'/library.php';
|
||||||
|
require_once SERVER.'/database.php';
|
||||||
// autoloader map
|
|
||||||
const MAP = [
|
|
||||||
// 'Class' => 'path/to/class.php',
|
|
||||||
|
|
||||||
// server-level classes
|
|
||||||
'App' => SERVER.'/app/app.php',
|
|
||||||
'Database' => SERVER.'/app/database.php',
|
|
||||||
'Request' => SERVER.'/app/request.php',
|
|
||||||
|
|
||||||
// modules
|
|
||||||
'HomeModule' => SERVER.'/modules/HomeModule.php',
|
|
||||||
];
|
|
||||||
|
|
||||||
// autoloader
|
|
||||||
spl_autoload_register(function($class) {
|
|
||||||
if (isset(MAP[$class])) require_once MAP[$class];
|
|
||||||
});
|
|
374
server/database.php
Normal file
374
server/database.php
Normal file
|
@ -0,0 +1,374 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQLite database wrapper class. Provides a non-static interface to interact with a
|
||||||
|
* SQLite database in as simple a way as possible.
|
||||||
|
*
|
||||||
|
* The wrapper provides a simple-to-use database API using PDO's SQLite driver.
|
||||||
|
* It was designed to have method signatures very close to Laravel's Eloquent ORM. There
|
||||||
|
* are not, however, any ORM features in the wrapper. These must be handled at
|
||||||
|
* the model level.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The PDO handle.
|
||||||
|
*/
|
||||||
|
private PDO $c;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current working table.
|
||||||
|
*/
|
||||||
|
private string $table = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of queries executed.
|
||||||
|
*/
|
||||||
|
private int $queries = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The log of executed queries.
|
||||||
|
*/
|
||||||
|
private array $log = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The last error.
|
||||||
|
*/
|
||||||
|
private string $error = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array for the query builder.
|
||||||
|
*/
|
||||||
|
private array $builder = [
|
||||||
|
'where' => [],
|
||||||
|
'order' => [],
|
||||||
|
'limit' => 0,
|
||||||
|
'values' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a connection to the database.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the current working table.
|
||||||
|
*/
|
||||||
|
public function table(string $name): Database
|
||||||
|
{
|
||||||
|
$this->table = $name;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a table with the name of the current working table. Will drop
|
||||||
|
* the table if it already exists.
|
||||||
|
*/
|
||||||
|
public function create(array $columns): PDOStatement|false
|
||||||
|
{
|
||||||
|
$query = "CREATE TABLE IF NOT EXISTS $this->table (" . implode(', ', $columns) . ');';
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->query($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop the current working table if it exists.
|
||||||
|
*/
|
||||||
|
public function drop(): PDOStatement|false
|
||||||
|
{
|
||||||
|
$query = "DROP TABLE IF EXISTS $this->table;";
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->query($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current working table's schema.
|
||||||
|
*/
|
||||||
|
public function schema(): array
|
||||||
|
{
|
||||||
|
$query = "PRAGMA table_info($this->table);";
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->query($query)->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert data into the current working table. Pass an array of key/value
|
||||||
|
* pairs to insert one record, or an array of arrays to insert multiple. Returns
|
||||||
|
* the number of rows inserted, or false on failure.
|
||||||
|
*/
|
||||||
|
public function insert(array $data): int|false
|
||||||
|
{
|
||||||
|
// If the first element is not an array we can assume we're doing a single insert.
|
||||||
|
if (!isset($data[0])) {
|
||||||
|
$query = "INSERT INTO $this->table (" . implode(', ', array_keys($data)) . ')'
|
||||||
|
. ' VALUES (' . implode(', ', array_fill(0, count($data), '?')) . ');';
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->prepare($query)->execute(array_values($data));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we will build a multi-insert query.
|
||||||
|
$query = "INSERT INTO $this->table (" . implode(', ', array_keys($data[0])) . ') VALUES ';
|
||||||
|
$placeholders = [];
|
||||||
|
$values = [];
|
||||||
|
|
||||||
|
foreach ($data as $row) {
|
||||||
|
$placeholders[] = '(' . implode(', ', array_fill(0, count($row), '?')) . ')';
|
||||||
|
foreach ($row as $value) $values[] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query .= implode(', ', $placeholders) . ';';
|
||||||
|
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->prepare($query)->execute($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a default record into the current working table.
|
||||||
|
*/
|
||||||
|
public function insertDefaultValues(): int|false
|
||||||
|
{
|
||||||
|
$query = "INSERT INTO $this->table DEFAULT VALUES;";
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->prepare($query)->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a where clause to the builder. All values are paramaterized.
|
||||||
|
*/
|
||||||
|
public function where(string $column, string $operator, mixed $value): Database
|
||||||
|
{
|
||||||
|
$this->builder['where'][] = "$column $operator ?";
|
||||||
|
$this->builder['values'][] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an order clause to the builder.
|
||||||
|
*/
|
||||||
|
public function order(string $column, string $direction = 'ASC'): Database
|
||||||
|
{
|
||||||
|
$this->builder['order'] = "$column $direction";
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a limit in the builder.
|
||||||
|
*/
|
||||||
|
public function limit(int $limit): Database
|
||||||
|
{
|
||||||
|
$this->builder['limit'] = $limit;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a select query and return the result. By default selects the entire
|
||||||
|
* row. Optionally use fetchAll, but there is also the selectAll() alias method
|
||||||
|
* for this.
|
||||||
|
*/
|
||||||
|
public function select(string $what = '*', bool $fetchAll = false): array|false
|
||||||
|
{
|
||||||
|
$query = "SELECT $what FROM $this->table";
|
||||||
|
if (!empty($this->builder['where'])) $query .= " WHERE " . implode(' AND ', $this->builder['where']);
|
||||||
|
if (!empty($this->builder['order'])) $query .= " ORDER BY " . $this->builder['order'];
|
||||||
|
if (!empty($this->builder['limit'])) $query .= " LIMIT " . $this->builder['limit'];
|
||||||
|
|
||||||
|
$this->addToLog($query);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt = $this->c->prepare($query);
|
||||||
|
$stmt->execute($this->builder['values']);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$this->error = "Failed to execute query: " . $e->getMessage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->resetBuilder();
|
||||||
|
return $fetchAll ? $stmt->fetchAll() : $stmt->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete records from the current working table. Returns the number of rows
|
||||||
|
* deleted, or false on failure. Uses where clauses if set.
|
||||||
|
*/
|
||||||
|
public function delete(): int|false
|
||||||
|
{
|
||||||
|
$query = "DELETE FROM $this->table";
|
||||||
|
if (!empty($this->builder['where'])) $query .= " WHERE " . implode(' AND ', $this->builder['where']);
|
||||||
|
$this->addToLog($query);
|
||||||
|
|
||||||
|
$this->resetBuilder();
|
||||||
|
return $this->c->exec($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update records in the current working table. Returns the number of rows
|
||||||
|
* updated, or false on failure. Uses where clauses if set.
|
||||||
|
*/
|
||||||
|
public function update(array $data): int|false
|
||||||
|
{
|
||||||
|
$query = "UPDATE $this->table SET " . implode(', ', array_keys($data)) . ' = ?';
|
||||||
|
if (!empty($this->builder['where'])) $query .= " WHERE " . implode(' AND ', $this->builder['where']);
|
||||||
|
$this->addToLog($query);
|
||||||
|
|
||||||
|
$values = array_merge(array_values($data), $this->builder['values']);
|
||||||
|
|
||||||
|
$this->resetBuilder();
|
||||||
|
return $this->c->prepare($query)->execute($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of rows in the current working table. Can use where clauses.
|
||||||
|
*/
|
||||||
|
public function count(): int|false
|
||||||
|
{
|
||||||
|
return $this->select('COUNT(*)', true)[0]['COUNT(*)'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for $db->select(true)
|
||||||
|
*/
|
||||||
|
public function selectAll(string $what = '*'): array|false
|
||||||
|
{
|
||||||
|
return $this->select($what, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the given table exists.
|
||||||
|
*/
|
||||||
|
public function tableExists(string $name): bool
|
||||||
|
{
|
||||||
|
$query = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='$name';";
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->query($query)->fetchColumn() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the PDO instance; for when more complex operations are needed.
|
||||||
|
*/
|
||||||
|
public function c(): PDO
|
||||||
|
{
|
||||||
|
return $this->c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for PDO::prepare
|
||||||
|
*/
|
||||||
|
public function prepare(string $query): PDOStatement
|
||||||
|
{
|
||||||
|
return $this->c->prepare($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for PDO::lastInsertId
|
||||||
|
*/
|
||||||
|
public function lastInsertId(): int
|
||||||
|
{
|
||||||
|
return $this->c->lastInsertId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for PDO::exec
|
||||||
|
*/
|
||||||
|
public function exec(string $query): int
|
||||||
|
{
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->exec($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for PDO::beginTransaction
|
||||||
|
*/
|
||||||
|
public function begin(): bool
|
||||||
|
{
|
||||||
|
return $this->c->beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for PDO::commit
|
||||||
|
*/
|
||||||
|
public function commit(): bool
|
||||||
|
{
|
||||||
|
return $this->c->commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for PDO::rollBack
|
||||||
|
*/
|
||||||
|
public function rollBack(): bool
|
||||||
|
{
|
||||||
|
return $this->c->rollBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for PDO::query
|
||||||
|
*/
|
||||||
|
public function query(string $query): PDOStatement|false
|
||||||
|
{
|
||||||
|
$this->addToLog($query);
|
||||||
|
return $this->c->query($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the query to the log and increment the number of queries executed.
|
||||||
|
*/
|
||||||
|
private function addToLog(string $query): void
|
||||||
|
{
|
||||||
|
$this->log[] = $query;
|
||||||
|
$this->queries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the builder to it's default structure.
|
||||||
|
*/
|
||||||
|
public function resetBuilder(): void
|
||||||
|
{
|
||||||
|
$this->builder = [
|
||||||
|
'where' => [],
|
||||||
|
'order' => [],
|
||||||
|
'limit' => 0,
|
||||||
|
'values' => [],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the log of executed queries.
|
||||||
|
*/
|
||||||
|
public function log(): array
|
||||||
|
{
|
||||||
|
return $this->log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of queries executed.
|
||||||
|
*/
|
||||||
|
public function queries(): int
|
||||||
|
{
|
||||||
|
return $this->queries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the last error message.
|
||||||
|
*/
|
||||||
|
public function error(): string
|
||||||
|
{
|
||||||
|
return $this->error;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
class HomeModule
|
|
||||||
{
|
|
||||||
public static function home(App $app)
|
|
||||||
{
|
|
||||||
echo 'Welcome to the home module!';
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user