Analysis of the advantages of PHP singleton mode

小云云
Release: 2023-03-20 17:50:01
Original
1747 people have browsed it

1. What is singleton mode?

1. Meaning
As an object creation mode, the singleton mode ensures that there is only one instance of a certain class, and it 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 required to save the only instance of the class:

private static $_instance;
Copy after login




(2). Constructors and clone functions must be declared private to prevent external programs from using new classes and thereby losing the meaning of the singleton mode:

private function __construct()   
{   
    $this->_db = pg_connect('xxxx');  
}   
private function __clone()  
{  
}//覆盖__clone()方法,禁止克隆
Copy after login



(3). A public static method (usually the getInstance method) must be provided to access this instance, thereby returning a reference to the unique instance

public static function getInstance()    
{    
    if(! (self::$_instance instanceof self) )   
    {    
        self::$_instance = new self();    
    }  
    return self::$_instance;    
  
}
Copy after login


2. Why use a singleton model?

Most people understand the purpose of the singleton pattern literally, thinking that it saves system resources, avoids repeated instantiation, and is a kind of "family planning". And PHP Every time the page is executed, all resources will be cleared from the memory. Therefore, the singleton in PHP actually needs to be re-instantiated every time it is run, thus losing the meaning of repeated instantiation of the singleton. Just start from In this respect, PHP's singleton is indeed a bit disappointing. But does a singleton only have this function and application? The answer is no, let's take a look.

The application of PHP is mainly in database applications, so there will be a large number of database operations in an application. When developing in an object-oriented way (nonsense), if you use the singleton mode, you can avoid a large number of new operations. resources consumed.
If a class is needed in the system to globally control certain configuration information, it can be easily implemented using the singleton mode. This can be found in the FrontController part of the zend Framework.
In a page request, it is easy to debug because all the code (such as database operation class db) is concentrated in one class. We can set hooks in the class and output logs to avoid var_dump and echo everywhere. 1. Disadvantages of PHP:


The PHP language is an interpreted scripting language. This operating mechanism causes all related resources to be recycled after each PHP page is interpreted and executed. 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) Interaction between application program and database

There will be a large number of database operations in an application, such as To connect 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 a class is needed to globally control certain configuration information in the system, it can be easily implemented using the singleton mode.

3. How to implement singleton mode?

1. Ordinary database access example:

##
<?php  
......  
//初始化一个数据库句柄  
$db = new DB(...);  
   
//添加用户信息  
$db->addUserInfo(...);  
   
......  
   
//在函数中访问数据库,查找用户信息  
function getUserInfo()  
{  
    $db = new DB(...);//再次new 数据库类,和数据库建立连接  
    $db = query(....);//根据查询语句访问数据库  
}  
   
?>
Copy after login


2、应用单例模式对数据库进行操作:

<?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(...);      ?>
Copy after login

下面的代码是PDO操作数据库类的一个封装,采用了单例模式:



/**

* 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 Update

* @param String $table Table name

* @param Array $arrayDataValue Field and value

* @param String $where condition

* @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 insert

* @param String $table table name

* @param Array $arrayDataValue fields and values

* @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 Overwrite mode insert

* @param String $table table name

* @param Array $arrayDataValue fields and values

* @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 Delete

*

* @param String $table table name

* @param String $where condition

* @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;

    }

     

    /**

* Get the maximum field value

* @param string $table table name

* @param string $field_name field name

* @param string $where condition

*/

    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;

    }

     

    /**

* Get the number of specified columns

* @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'];

    }

     

    /**

* Get table engine

* @param String $dbName Library name

* @param String $tableName Table name

* @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 Transaction starts

*/

    private function beginTransaction()

    {

        $this->dbh->beginTransaction();

    }

     

    /**

* commit transaction submission

*/

    private function commit()

    {

        $this->dbh->commit();

    }

     

    /**

* rollback transaction rollback

*/

    private function rollback()

    {

        $this->dbh->rollback();

    }

     

    /**

* Transaction handles multiple SQL statements through transactions

* Before calling, you need to use getTableEngine to determine whether the table engine supports transactions

*

* @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 Checks whether the specified field exists in the specified data table

*

* @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 Gets all field names in the specified data table

*

* @param String $table table name

* @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 captures PDO error information

*/

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

    }

     

    /**

* Output error message

*

* @param String $strErrMsg

*/

    private function outputError($strErrMsg)

    {

        throw new Exception('MySQL Error: '.$strErrMsg);

    }

     

    /**

* destruct Close database connection

*/

    public function destruct()

    {

        $this->dbh = null;

    }

}

?>



调用方法:

1

2

3

4

5

6

require 'MyPDO.class.php';

$db = MyPDO::getInstance('localhost', 'root', '123456', 'test', 'utf8');

$db->query("select count(*) frome table");

$db->destruct();

?>

The above is the detailed content of Analysis of the advantages of PHP singleton mode. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template