<?php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); /** * PDOi类(单例模式) */ class PDOi { private static ?PDOi $instance = null; /** * 将构造方法声明为private防止通过“new PDOi()”创建实例 */ private function __construct() { } /** * 将克隆方法声明为private防止复制实例 */ private function __clone() { } /** * 获取PDOi实例(单例) * * @return PDOi PDOi实例(单例) */ public static function getInstance(): PDOi { if (self::$instance === null) { echo '[new]PDOi实例成功' . PHP_EOL; self::$instance = new self(); } echo '[get]PDOi实例成功' . PHP_EOL; return self::$instance; } } $instance1 = PDOi::getInstance(); $instance2 = PDOi::getInstance(); $instance3 = PDOi::getInstance(); $instance4 = PDOi::getInstance(); $instance5 = PDOi::getInstance(); // [new]PDOi实例成功 // [get]PDOi实例成功 // [get]PDOi实例成功 // [get]PDOi实例成功 // [get]PDOi实例成功 // [get]PDOi实例成功 // 从输出结果可以清楚地看到,虽然五次获取实例,但是只执行了一次实例化操作。 //========== 总结 ==========// // 1、实现单例模式要点有四个: // ① 将构造方法 __construct() 声明为 private 禁止使用 new 关键字创建实例; // ② 将克隆方法 __clone() 声明为 private 禁止克隆实例; // ③ 定义一个名为 $instance 的 private static 属性,用于保存唯一的实例; // ④ 定义一个名为 getInstance() 的 public static 方法,用于获取(唯一的)实例。
<?php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); $driver = 'mysql'; // 数据库驱动 $host = 'localhost'; // 主机地址 $dbname = 'test_db'; // 数据库名 $port = 3306; // 服务端口号 $charset = 'utf8mb4'; // 字符编码 $username = 'zhangsan'; // 账号 $password = 'pwd-1234'; // 密码 /** * PDOi类(单例模式) */ class PDOi { private ?PDO $pdo = null; // PDO类实例(该属性声不声明为static均可) private static ?PDOi $instance = null; // PDOi类实例(该属性必须声明为static) /** * 将构造方法声明为private防止通过“new PDOi()”创建实例 */ private function __construct() { } /** * 将克隆方法声明为private防止复制实例 */ private function __clone() { } /** * 获取PDOi实例(单例) * * @return PDOi PDOi实例(单例) */ private static function getInstance(): PDOi { if (self::$instance === null) { self::$instance = new self(); global $driver; global $host; global $dbname; global $port; global $charset; global $username; global $password; // 构造数据源名称(Data Source Name)字符串 $dsn = "$driver:"; $dsn .= "host=$host;"; $dsn .= "dbname=$dbname;"; $dsn .= "port=$port;"; $dsn .= "charset=$charset;"; // PDO连接选项 $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES $charset", PDO::ATTR_EMULATE_PREPARES => false, ]; // 创建PDO类实例 try { self::$instance->pdo = new PDO($dsn, $username, $password, $options); } catch (PDOException $e) { exit('创建PDO类实例失败:' . $e->getMessage()); } } return self::$instance; } /** * 执行语句 * * @param string $query SQL语句 * @param array $params 参数 * @return PDOStatement|false 执行成功返回PDOStatement实例,否则返回false */ public static function execute(string $query, array $params = []): PDOStatement|false { // 预处理要执行的语句 try { $sth = self::getInstance()->pdo->prepare($query); } catch (PDOException) { $sth = false; } // 绑定参数 if ($sth instanceof PDOStatement) { foreach ($params as $field => $value) { try { $sth->bindValue(":$field", $value); } catch (PDOException) { $sth = false; break; // 有一个参数绑定失败,后面的参数已经没有绑定的必要了 } } } // 执行语句 if ($sth instanceof PDOStatement && $sth->execute() === false) { $sth = false; } return $sth; } } $query = 'SELECT * FROM `prefix_user` WHERE `uid` = :uid LIMIT 1'; $params = ['uid' => 9527]; $sth = PDOi::execute($query, $params); if ($sth instanceof PDOStatement) { $fetchAll = $sth->fetchAll(); $row = $fetchAll[0] ?? []; if ($row) { echo "俺叫{$row['name']}({$row['gender']}),今年{$row['age']}岁。" . PHP_EOL; // 俺叫张三(男),今年18岁。 } }
Copyright © 2024 码农人生. All Rights Reserved