I created this code where I create an instance of the database and work with it. Now I'm trying to convert the code to a static form, but I can't.
$pdo = new PDO('sqlite:src/chinook.db');
$sql = "CREATE TABLE IF NOT EXISTS uzivatele(
uzivatelId INTEGER PRIMARY KEY,
jmeno TEXT,
prijmeni TEXT,
body INTEGER
);";
$statement = $pdo->prepare($sql);
$statement->execute();
function dropTable($pdo,$name)
{
$sql = "DROP TABLE $name";
$statement = $pdo->prepare($sql);
$statement->execute();
}
...
static This is how I have a class implemented for pdo (according to the manual) and I would like to implement static methods, such as createTable, but I can't redo it
class Db
{
protected static $pdo = null;
public static function get(): \PDO
{
return self::$pdo ?? (self::$pdo = new \PDO(
'sqlite:hw-06.db',
null,
null,
[
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
]
));
}
}
use App\Db;
class Account
{
...
public static function createTable(): void
{
$db = Db::get();
$sql = "CREATE TABLE IF NOT EXISTS uzivatele(
uzivatelId INTEGER PRIMARY KEY,
jmeno TEXT,
prijmeni TEXT,
body INTEGER
);";
$statement = $db->prepare($sql);
$statement->execute();
}
index.php Account::createTable();
CodePudding user response:
If u want to implement a simple singleton, u can use the "getInstance()" concept and combine with "__callStatic" and "call_user_func_array" to make a PDO functions to be static too, all PDO and Database class functions will become static:
<?php
declare(strict_types = 1);
/*
* PDO database class - only one connection alowed
*/
final class Database
{
/**
* @var PDO $connection The connection
*/
private $connection;
/**
* @var Database $instance The single instance
*/
private static $instance;
/**
* @var string $engine The engine of connection
*/
private $engine = 'sqlite:persistence.db'; // sqlite::memory:
/**
* @var array $options Default option to PDO connection
*/
private $options = [
PDO::ATTR_PERSISTENT => true,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
];
/**
* Private constructor to prevent instance
*
* @throws \Throwable
* @return void
*/
private function __construct()
{
try {
$this->connection = new PDO($this->engine, null, null, $this->options);
}
catch (\Throwable $error) {
error_log("{$error->getMessage()}");
}
}
/**
* Get an instance of the Database
*
* @return PDO
*/
private static function getInstance(): PDO
{
// If no instance then make one
if (!self::$instance) {
self::$instance = new self;
}
return self::$instance->connection;
}
/**
* Transpiler of static methods for PDOStatements
*
* @var string $method The PDO static method
* @var array $args
* @return string|PDOStatement
*/
public static function __callStatic(string $method, array $args)
{
return call_user_func_array(array(self::getInstance(), $method), $args);
}
/**
* Destroying PDO connection
*
* @return void
*/
public function __destruct()
{
if (!empty($this->connection)) {
unset($this->connection);
}
}
/**
* Magic method clone is empty to prevent duplication of connection
*/
public function __clone() { }
public function __wakeup() { }
public function __toString() { }
}
to use there:
<?php
require_once __DIR__ . '/Database.php';
Database::exec('CREATE TABLE IF NOT EXISTS uzivatele (
uzivatelId INTEGER PRIMARY KEY,
jmeno TEXT,
prijmeni TEXT,
body INTEGER
);');
Database::exec("INSERT INTO uzivatele (jmeno, prijmeni, body) VALUES ('test', 'test', 1);");
var_dump(Database::lastInsertId());
$stmt = Database::prepare("SELECT * FROM uzivatele;");
$stmt->execute();
$data = $stmt->fetchAll();
var_dump($data);
note that "prepared statments objects" are still like objects!
i dont see any problem in using database connections as static, if they are not used in parallel, there is no problem, it even reduces the overhead of creating many connections with the database. but be careful, in some cases it may not be beneficial, as in cases where the code is not being executed by a CGI or FastCGI but by a wrapper, it can cause slowdowns and even give a problem!