Home > Article > Backend Development > How to implement singleton pattern in php
In this article, we will share with you how to implement the singleton mode in PHP and tell you why you use the singleton mode. Interested friends can refer to it.
1. What is the singleton pattern?
1. Meaning
As an object creation pattern, the singleton pattern ensures that a class has only one instance, instantiates itself, and provides this instance globally to the entire system. It does not create a copy of the instance, but returns a reference to the instance stored internally in the singleton class.
2. Three key points of singleton mode:
(1).
A static member variable is needed to save the only instance of the class:
private static $_instance;
(2).
Constructors and clone functions must be declared private to prevent external programs from new classes and thus lose the meaning of the singleton mode:
private function __construct() { $this->_db = pg_connect('xxxx'); } private function __clone() { }//覆盖__clone()方法,禁止克隆
(3). An access to this instance must be provided The public static method (usually the getInstance method), thus returning a reference to the unique instance
public static function getInstance() { if(! (self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; }
2. Why use the singleton mode?
1. Disadvantages of PHP:
The PHP language is an interpreted scripting language. This operating mechanism ensures that after each PHP page is interpreted and executed, all related resources will be recycled. In other words, PHP has no way to make an object resident in memory at the language level. This is different from compiled types such as asp.net and Java. For example, in Java, a singleton will always exist throughout the life cycle of the application. Variables are cross-page level and can truly make this instance unique in the application life cycle. However, in PHP, all variables, whether they are global variables or static members of the class, are page-level. Every time the page is executed, a new object will be re-established and will be cleared after the page is executed. It seems that PHP The singleton mode is meaningless, so I think the PHP singleton mode is very meaningful only when multiple application scenarios occur in a single page-level request and need to share the same object resource.
2. Application occasions of singleton mode in PHP:
(1), application and database interaction
There will be a large number of database operations in an application, such as connecting to the database through a database handle. Using the singleton mode can avoid a large number of new operations, because each new operation consumes memory resources and system resources.
(2) Control configuration information
If there is a class in the system to globally control certain configuration information,
Then it can be easily implemented using the singleton mode.
3. How to implement the singleton mode?
1. Ordinary database access example:
<?php ...... //初始化一个数据库句柄 $db = new DB(...); //添加用户信息 $db->addUserInfo(...); ...... //在函数中访问数据库,查找用户信息 function getUserInfo() { $db = new DB(...);//再次new 数据库类,和数据库建立连接 $db = query(....);//根据查询语句访问数据库 } ?>
2. Apply singleton mode to operate the database:
<?php class DB { private $_db; private static $_instance; private function __construct(...) { $this->_db = pg_connect(...);//postgrsql } private function __clone() {}; //覆盖__clone()方法,禁止克隆 public static function getInstance() { if(! (self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; } public function addUserInfo(...) { } public function getUserInfo(...) { } } //test $db = DB::getInstance(); $db->addUserInfo(...); $db->getUserInfo(...); ?>
The following code is an encapsulation of the PDO operation database class, using the singleton mode:
<?php /** * MyPDO */ class MyPDO { protected static $_instance = null; protected $dbName = ''; protected $dsn; protected $dbh; /** * 构造 * * @return MyPDO */ private function __construct($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset) { try { $this->dsn = 'mysql:host='.$dbHost.';dbname='.$dbName; $this->dbh = new PDO($this->dsn, $dbUser, $dbPasswd); $this->dbh->exec('SET character_set_connection='.$dbCharset.', character_set_results='.$dbCharset.', character_set_client=binary'); } catch (PDOException $e) { $this->outputError($e->getMessage()); } } /** * 防止克隆 * */ private function __clone() {} /** * Singleton instance * * @return Object */ public static function getInstance($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset) { if (self::$_instance === null) { self::$_instance = new self($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset); } return self::$_instance; } /** * Query 查询 * * @param String $strSql SQL语句 * @param String $queryMode 查询方式(All or Row) * @param Boolean $debug * @return Array */ public function query($strSql, $queryMode = 'All', $debug = false) { if ($debug === true) $this->debug($strSql); $recordset = $this->dbh->query($strSql); $this->getPDOError(); if ($recordset) { $recordset->setFetchMode(PDO::FETCH_ASSOC); if ($queryMode == 'All') { $result = $recordset->fetchAll(); } elseif ($queryMode == 'Row') { $result = $recordset->fetch(); } } else { $result = null; } return $result; } /** * Update 更新 * * @param String $table 表名 * @param Array $arrayDataValue 字段与值 * @param String $where 条件 * @param Boolean $debug * @return Int */ public function update($table, $arrayDataValue, $where = '', $debug = false) { $this->checkFields($table, $arrayDataValue); if ($where) { $strSql = ''; foreach ($arrayDataValue as $key => $value) { $strSql .= ", `$key`='$value'"; } $strSql = substr($strSql, 1); $strSql = "UPDATE `$table` SET $strSql WHERE $where"; } else { $strSql = "REPLACE INTO `$table` (`".implode('`,`', array_keys($arrayDataValue))."`) VALUES ('".implode("','", $arrayDataValue)."')"; } if ($debug === true) $this->debug($strSql); $result = $this->dbh->exec($strSql); $this->getPDOError(); return $result; } /** * Insert 插入 * * @param String $table 表名 * @param Array $arrayDataValue 字段与值 * @param Boolean $debug * @return Int */ public function insert($table, $arrayDataValue, $debug = false) { $this->checkFields($table, $arrayDataValue); $strSql = "INSERT INTO `$table` (`".implode('`,`', array_keys($arrayDataValue))."`) VALUES ('".implode("','", $arrayDataValue)."')"; if ($debug === true) $this->debug($strSql); $result = $this->dbh->exec($strSql); $this->getPDOError(); return $result; } /** * Replace 覆盖方式插入 * * @param String $table 表名 * @param Array $arrayDataValue 字段与值 * @param Boolean $debug * @return Int */ public function replace($table, $arrayDataValue, $debug = false) { $this->checkFields($table, $arrayDataValue); $strSql = "REPLACE INTO `$table`(`".implode('`,`', array_keys($arrayDataValue))."`) VALUES ('".implode("','", $arrayDataValue)."')"; if ($debug === true) $this->debug($strSql); $result = $this->dbh->exec($strSql); $this->getPDOError(); return $result; } /** * Delete 删除 * * @param String $table 表名 * @param String $where 条件 * @param Boolean $debug * @return Int */ public function delete($table, $where = '', $debug = false) { if ($where == '') { $this->outputError("'WHERE' is Null"); } else { $strSql = "DELETE FROM `$table` WHERE $where"; if ($debug === true) $this->debug($strSql); $result = $this->dbh->exec($strSql); $this->getPDOError(); return $result; } } /** * execSql 执行SQL语句 * * @param String $strSql * @param Boolean $debug * @return Int */ public function execSql($strSql, $debug = false) { if ($debug === true) $this->debug($strSql); $result = $this->dbh->exec($strSql); $this->getPDOError(); return $result; } /** * 获取字段最大值 * * @param string $table 表名 * @param string $field_name 字段名 * @param string $where 条件 */ public function getMaxValue($table, $field_name, $where = '', $debug = false) { $strSql = "SELECT MAX(".$field_name.") AS MAX_VALUE FROM $table"; if ($where != '') $strSql .= " WHERE $where"; if ($debug === true) $this->debug($strSql); $arrTemp = $this->query($strSql, 'Row'); $maxValue = $arrTemp["MAX_VALUE"]; if ($maxValue == "" || $maxValue == null) { $maxValue = 0; } return $maxValue; } /** * 获取指定列的数量 * * @param string $table * @param string $field_name * @param string $where * @param bool $debug * @return int */ public function getCount($table, $field_name, $where = '', $debug = false) { $strSql = "SELECT COUNT($field_name) AS NUM FROM $table"; if ($where != '') $strSql .= " WHERE $where"; if ($debug === true) $this->debug($strSql); $arrTemp = $this->query($strSql, 'Row'); return $arrTemp['NUM']; } /** * 获取表引擎 * * @param String $dbName 库名 * @param String $tableName 表名 * @param Boolean $debug * @return String */ public function getTableEngine($dbName, $tableName) { $strSql = "SHOW TABLE STATUS FROM $dbName WHERE Name='".$tableName."'"; $arrayTableInfo = $this->query($strSql); $this->getPDOError(); return $arrayTableInfo[0]['Engine']; } /** * beginTransaction 事务开始 */ private function beginTransaction() { $this->dbh->beginTransaction(); } /** * commit 事务提交 */ private function commit() { $this->dbh->commit(); } /** * rollback 事务回滚 */ private function rollback() { $this->dbh->rollback(); } /** * transaction 通过事务处理多条SQL语句 * 调用前需通过getTableEngine判断表引擎是否支持事务 * * @param array $arraySql * @return Boolean */ public function execTransaction($arraySql) { $retval = 1; $this->beginTransaction(); foreach ($arraySql as $strSql) { if ($this->execSql($strSql) == 0) $retval = 0; } if ($retval == 0) { $this->rollback(); return false; } else { $this->commit(); return true; } } /** * checkFields 检查指定字段是否在指定数据表中存在 * * @param String $table * @param array $arrayField */ private function checkFields($table, $arrayFields) { $fields = $this->getFields($table); foreach ($arrayFields as $key => $value) { if (!in_array($key, $fields)) { $this->outputError("Unknown column `$key` in field list."); } } } /** * getFields 获取指定数据表中的全部字段名 * * @param String $table 表名 * @return array */ private function getFields($table) { $fields = array(); $recordset = $this->dbh->query("SHOW COLUMNS FROM $table"); $this->getPDOError(); $recordset->setFetchMode(PDO::FETCH_ASSOC); $result = $recordset->fetchAll(); foreach ($result as $rows) { $fields[] = $rows['Field']; } return $fields; } /** * getPDOError 捕获PDO错误信息 */ private function getPDOError() { if ($this->dbh->errorCode() != '00000') { $arrayError = $this->dbh->errorInfo(); $this->outputError($arrayError[2]); } } /** * debug * * @param mixed $debuginfo */ private function debug($debuginfo) { var_dump($debuginfo); exit(); } /** * 输出错误信息 * * @param String $strErrMsg */ private function outputError($strErrMsg) { throw new Exception('MySQL Error: '.$strErrMsg); } /** * destruct 关闭数据库连接 */ public function destruct() { $this->dbh = null; } } ?>
Calling method:
<?php require 'MyPDO.class.php'; $db = MyPDO::getInstance('localhost', 'root', '123456', 'test', 'utf8'); $db->query("select count(*) frome table"); $db->destruct(); ?>
The above content It’s about how to implement singleton mode in PHP. Hope it helps everyone.
Related recommendations:
Easy to understand PHP design pattern singleton mode
Factory pattern and singleton pattern in PHP design pattern Difference
Analysis of singleton pattern in PHP design pattern
The above is the detailed content of How to implement singleton pattern in php. For more information, please follow other related articles on the PHP Chinese website!