2019-01-14 21:32:55 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace AirQuality;
|
|
|
|
|
2019-01-15 16:37:46 +00:00
|
|
|
use \SBRL\TomlConfig;
|
|
|
|
use Psr\Container\ContainerInterface;
|
|
|
|
|
2019-01-14 21:32:55 +00:00
|
|
|
/**
|
|
|
|
* Holds the main database connection.
|
|
|
|
*/
|
|
|
|
class Database
|
|
|
|
{
|
2019-06-20 23:02:26 +00:00
|
|
|
/** @var TomlConfig */
|
|
|
|
private $settings;
|
|
|
|
/** @var \SBRL\PerformanceCounter */
|
|
|
|
private $perfcounter;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether the database connection should be read only or not.
|
|
|
|
* Defaults to true, as we don't need to write _anything_ to the database.
|
|
|
|
* @var bool
|
|
|
|
*/
|
2019-01-14 21:32:55 +00:00
|
|
|
private const read_only = true;
|
2019-06-23 12:13:28 +00:00
|
|
|
/**
|
|
|
|
* The internal PDO connection to the database.
|
|
|
|
* @var \PDO
|
|
|
|
*/
|
2019-01-14 21:32:55 +00:00
|
|
|
private $connection;
|
|
|
|
|
2019-06-23 12:13:28 +00:00
|
|
|
/**
|
|
|
|
* The PDO connection options.
|
|
|
|
* @var array
|
|
|
|
*/
|
2019-01-14 21:32:55 +00:00
|
|
|
private $pdo_options = [
|
|
|
|
// https://devdocs.io/php/pdo.setattribute
|
2019-01-15 15:46:24 +00:00
|
|
|
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
|
|
|
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
|
|
|
|
\PDO::ATTR_EMULATE_PREPARES => false,
|
|
|
|
\PDO::ATTR_AUTOCOMMIT => false
|
2019-01-14 21:32:55 +00:00
|
|
|
];
|
|
|
|
|
2019-06-23 12:13:28 +00:00
|
|
|
/**
|
|
|
|
* Initialises a new Database class instance that manages a single
|
|
|
|
* connection to a database.
|
|
|
|
* @param TomlConfig $in_settings The settings object to use to connect to the database
|
|
|
|
* @param \SBRL\PerformanceCounter $in_perfcounter The performance counter for debugging purposes.
|
|
|
|
*/
|
2019-06-20 23:02:26 +00:00
|
|
|
function __construct(TomlConfig $in_settings, \SBRL\PerformanceCounter $in_perfcounter) {
|
2019-01-14 21:32:55 +00:00
|
|
|
$this->settings = $in_settings;
|
2019-06-20 23:02:26 +00:00
|
|
|
$this->perfcounter = $in_perfcounter;
|
2019-01-15 16:37:46 +00:00
|
|
|
|
|
|
|
$this->connect(); // Connect automagically
|
2019-01-14 21:32:55 +00:00
|
|
|
}
|
|
|
|
|
2019-06-23 12:13:28 +00:00
|
|
|
/**
|
|
|
|
* Initailises the connection to the database according to the currently loaded settings.
|
|
|
|
* @return void
|
|
|
|
*/
|
2019-01-14 21:32:55 +00:00
|
|
|
public function connect() {
|
2019-06-20 23:02:26 +00:00
|
|
|
$this->perfcounter->start("dbconnect");
|
2019-01-14 21:32:55 +00:00
|
|
|
$this->connection = new \PDO(
|
|
|
|
$this->get_connection_string(),
|
|
|
|
$this->settings->get("database.username"),
|
|
|
|
$this->settings->get("database.password"),
|
2019-01-15 15:46:24 +00:00
|
|
|
$this->pdo_options
|
2019-01-14 21:32:55 +00:00
|
|
|
);
|
|
|
|
// Make this connection read-only
|
|
|
|
if(self::read_only)
|
|
|
|
$this->connection->query("SET SESSION TRANSACTION READ ONLY;");
|
2019-06-20 23:02:26 +00:00
|
|
|
$this->perfcounter->end("dbconnect");
|
2019-01-14 21:32:55 +00:00
|
|
|
}
|
|
|
|
|
2019-06-23 12:13:28 +00:00
|
|
|
/**
|
|
|
|
* Makes a query against the database.
|
|
|
|
* @param string $sql The (potentially parametised) query to make.
|
|
|
|
* @param array $variables Optional. The variables to substitute into the SQL query.
|
|
|
|
* @return \PDOStatement The result of the query, as a PDOStatement.
|
|
|
|
*/
|
2019-01-15 16:16:00 +00:00
|
|
|
public function query($sql, $variables = []) {
|
2019-06-22 10:50:23 +00:00
|
|
|
// Replace tabs with spaces for debugging purposes
|
|
|
|
$sql = str_replace("\t", " ", $sql);
|
|
|
|
|
2019-06-22 20:08:12 +00:00
|
|
|
if($this->settings->get("env.mode") == "development") {
|
2019-06-23 12:13:28 +00:00
|
|
|
error_log("[Database/SQL:Variables]" . var_export($variables, true));
|
|
|
|
error_log("[Database/SQL:Exec] $sql");
|
2019-06-22 20:08:12 +00:00
|
|
|
}
|
2019-02-24 17:18:36 +00:00
|
|
|
|
2019-01-14 21:32:55 +00:00
|
|
|
// FUTURE: Optionally cache prepared statements?
|
2019-06-22 10:50:23 +00:00
|
|
|
$statement = $this->connection->prepare($sql);
|
2019-01-15 17:02:24 +00:00
|
|
|
$statement->execute($variables);
|
2019-06-30 16:24:02 +00:00
|
|
|
|
|
|
|
if($this->settings->get("env.mode") == "development") {
|
|
|
|
$warnings = $this->connection->query("SHOW WARNINGS;")->fetchAll();
|
|
|
|
error_log("Warnings: " . var_export($warnings, true));
|
|
|
|
}
|
|
|
|
|
2019-01-15 17:02:24 +00:00
|
|
|
return $statement; // fetchColumn(), fetchAll(), etc. are defined on the statement, not the return value of execute()
|
2019-01-14 21:32:55 +00:00
|
|
|
}
|
|
|
|
|
2019-06-21 21:05:13 +00:00
|
|
|
/**
|
|
|
|
* Returns the connection string to use to connect to the database.
|
|
|
|
* This is calculated from the values specified in the settings file.
|
|
|
|
* @return string The connection string.
|
|
|
|
*/
|
2019-01-14 21:32:55 +00:00
|
|
|
private function get_connection_string() {
|
|
|
|
return "{$this->settings->get("database.type")}:host={$this->settings->get("database.host")};dbname={$this->settings->get("database.name")};charset=utf8mb4";
|
|
|
|
}
|
2019-01-15 16:37:46 +00:00
|
|
|
|
2019-01-14 21:32:55 +00:00
|
|
|
}
|