PHP SQLite PDO - 更改为静态

PHP SQLite PDO - Change to static

我在创建数据库实例并使用它的地方创建了这段代码。现在我正在尝试将代码转换为静态形式,但我做不到。

    $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();
        }

...

静态 这就是我为 pdo 实现 class 的方式(根据手册),我想实现静态方法,例如 createTable,但我无法重做

    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();

如果你想实现一个简单的单例,你可以使用“getInstance()”概念并结合“__callStatic”和“call_user_func_array”使PDO函数成为静态的同样,所有 PDO 和数据库 class 函数都将变为静态:

<?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() { }
}

在那里使用:

<?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);


请注意,“准备好的语句对象”仍然像对象!

我认为使用静态数据库连接没有任何问题,如果它们不是并行使用,则没有问题,它甚至减少了与数据库建立许多连接的开销。但要小心,在某些情况下它可能没有好处,因为在代码不是由 CGI 或 FastCGI 而是由包装器执行的情况下,它可能会导致速度减慢甚至出现问题!