PHP SQLite PDO - 更改为静态

Posted

技术标签:

【中文标题】PHP SQLite PDO - 更改为静态【英文标题】:PHP SQLite PDO - Change to static 【发布时间】:2021-12-27 22:42:21 【问题描述】:

我创建了这段代码,我在其中创建了一个数据库实例并使用它。现在我正在尝试将代码转换为静态形式,但我不能。

    $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 实现类的方式(根据手册),我想实现静态方法,例如 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 帐户::createTable();

【问题讨论】:

“我不能重做”是什么意思?你遇到了什么问题? 重点是我不能把第一个版本转成静态版本 为什么不呢?再说一遍,你遇到了什么问题? 您不能也不应该尝试将 PDO 方法更改为静态。您上面的代码应该可以正常工作。使用 PDO 时,您必须有一个实际的实例 这正是您的Db 类所做的,将PDO 实例作为singleton 提供。你的问题真的不清楚。我已经问了两次你遇到了什么问题,除了猜测之外,你没有提供任何细节。我建议你先写一些代码,如果你有具体问题再回来 【参考方案1】:

如果你想实现一个简单的单例,你可以使用“getInstance()”的概念,结合“__callStatic”和“call_user_func_array”使PDO函数也成为静态的,所有的PDO和Database类函数都会变成静态:

<?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 而是由包装器执行的情况下,它可能会导致速度变慢甚至出现问题!

【讨论】:

以上是关于PHP SQLite PDO - 更改为静态的主要内容,如果未能解决你的问题,请参考以下文章

pdo sqlite 找不到驱动程序... php 文件未处理

在 PHP 中设置 SQLite3 PDO 驱动程序

MySQL更新,跳过PDO的空白字段

将 SQLite 数据库模式更改为读写

如何在 php 中启用 sqlite3 的 PDO 驱动程序?

PHP,PDO,SQLite INNER JOIN语句和变量