\PDO::ERRMODE_EXCEPTION, \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, \PDO::ATTR_EMULATE_PREPARES => false, \PDO::ATTR_AUTOCOMMIT => false ]; /** * 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. */ function __construct(TomlConfig $in_settings, \SBRL\PerformanceCounter $in_perfcounter) { $this->settings = $in_settings; $this->perfcounter = $in_perfcounter; $this->connect(); // Connect automagically } /** * Initailises the connection to the database according to the currently loaded settings. * @return void */ public function connect() { $this->perfcounter->start("dbconnect"); $this->connection = new \PDO( $this->get_connection_string(), $this->settings->get("database.username"), $this->settings->get("database.password"), $this->pdo_options ); // Make this connection read-only if(self::read_only) $this->connection->query("SET SESSION TRANSACTION READ ONLY;"); $this->perfcounter->end("dbconnect"); } /** * 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. */ public function query($sql, $variables = []) { // Replace tabs with spaces for debugging purposes $sql = str_replace("\t", " ", $sql); if($this->settings->get("env.mode") == "development") { error_log("[Database/SQL:Variables]" . var_export($variables, true)); error_log("[Database/SQL:Exec] $sql"); } // FUTURE: Optionally cache prepared statements? $statement = $this->connection->prepare($sql); $statement->execute($variables); if($this->settings->get("env.mode") == "development") { $warnings = $this->connection->query("SHOW WARNINGS;")->fetchAll(); error_log("Warnings: " . var_export($warnings, true)); } return $statement; // fetchColumn(), fetchAll(), etc. are defined on the statement, not the return value of execute() } /** * 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. */ 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"; } }