1. シングルトンパターンとは何ですか?
1. 意味
オブジェクト作成モードとして、シングルトン モードは、特定のクラスのインスタンスが 1 つだけ存在することを保証し、自身をインスタンス化し、このインスタンスをシステム全体にグローバルに提供します。インスタンスのコピーは作成されませんが、シングルトン クラス内に格納されているインスタンスへの参照を返します。
2. シングルトン パターンの 3 つの重要なポイント:
(1) クラスの唯一のインスタンスを保存するには、静的メンバー変数が必要です:
private static $_instance;
(2)。新しいクラスを使用して外部プログラムがシングルトン モードの意味を失わないようにするには、 private と宣言します:
private function __construct() { $this->_db = pg_connect('xxxx'); } private function __clone() { }//覆盖__clone()方法,禁止克隆
(3) このインスタンスにアクセスするパブリック静的メソッド (通常は getInstance メソッド) を返すために提供する必要があります。唯一のインスタンスへの参照
public static function getInstance() { if(! (self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; }
2. シングルトン モードを使用する理由
ほとんどの人は、シングルトン パターンの目的を文字通りの意味から理解し、システム リソースを節約し、繰り返しのインスタンス化を回避し、一種の「家族計画」であると考えています。そして、PHP はすべての実行を完了し、ページからすべてのリソースを削除します。したがって、PHP のシングルトンは実行されるたびに実際に再インスタンス化する必要があるため、この点だけから見ても、PHP のシングルトンは確かに少し残念です。シングルトンにはこの機能とアプリケーションしかありませんか? 答えは「いいえ」です。見てみましょう。
PHP は主にデータベース アプリケーションで使用されるため、アプリケーション内で大量のデータベース操作が発生します。オブジェクト指向で開発する場合 (ナンセンス)、シングルトン モードを使用すると、大量のデータベース操作を回避できます。新しい操作によって消費されるリソース。
特定の構成情報をグローバルに制御するためにシステム内のクラスが必要な場合は、シングルトン モードを使用して簡単に実装できます。これについては、zend フレームワークの FrontController 部分を参照してください。
ページリクエストでは、すべてのコード (データベース操作クラス db など) が 1 つのクラスに集中しているため、クラス内にフックを設定し、どこでも var_dump や echo を回避してログを出力できるため、デバッグが簡単です。 1. PHP の欠点:
PHP 言語は解釈されたスクリプト言語です。この動作メカニズムにより、各 PHP ページが解釈および実行された後に、関連するすべてのリソースがリサイクルされます。言い換えれば、PHP には言語レベルでオブジェクトをメモリに常駐させる方法がありません。これは、たとえば Java では、ライフサイクル全体を通じて常に存在します。変数はページ間レベルであり、アプリケーションのライフサイクル内でこのインスタンスを真に一意にすることができます。ただし、PHP では、グローバル変数であろうとクラスの静的メンバーであろうと、すべての変数はページ レベルであり、ページが実行されるたびに新しいオブジェクトが再確立され、ページの実行後にクリアされます。 PHP のシングルトン モードは意味がないようなので、単一のページ レベルのリクエストで複数のアプリケーション シナリオが発生し、同じオブジェクト リソースを共有する必要がある場合にのみ、PHP シングルトン モードが非常に意味があると思います。
2. PHP におけるシングルトン モードの適用場面:
(1) アプリケーションとデータベース間の対話
アプリケーションでは、データベース ハンドルを介してデータベースに接続する行為など、多数のデータベース操作が行われます。単一の使用 サンプル モードでは、新しい操作が行われるたびにメモリ リソースとシステム リソースが消費されるため、多数の新しい操作を回避できます。
(2) 構成情報の制御
システム内の特定の構成情報をグローバルに制御するためにクラスが必要な場合、シングルトン モードを使用して簡単に実装できます
3. シングルトン モードを実装するにはどうすればよいですか?
1. 通常のデータベースアクセスの例:
<?php ...... //初始化一个数据库句柄 $db = new DB(...); //添加用户信息 $db->addUserInfo(...); ...... //在函数中访问数据库,查找用户信息 function getUserInfo() { $db = new DB(...);//再次new 数据库类,和数据库建立连接 $db = query(....);//根据查询语句访问数据库 } ?> ログイン後にコピー |
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(...); ?>
下面的代码是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($strS ql, $queryMode = 'すべて', $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; }
/** * アップデート アップデート @ 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; }
/** * 挿入 * @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; } /** * @return Int*/ public 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; } /** * @return Int*/ public 関数 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 ; }
/** * フィールドの最大値を取得します **/ パブリック関数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 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']; }
/** * テーブル エンジンを入手します * @return String*/ public function getTableEngine($dbName, $tableName) { $strSql = 「テーブルステータスを表示」 $dbName WHERE Name='".$tableName."'"; $arrayTableInfo = $this->query($strSql); $this->getPDOError(); return $arrayTableInfo[0]['Engine']; }
/** * beginTransaction トランザクションが開始されます */ private function beginTransaction() { $this->dbh->beginTransaction(); }
/** * トランザクション送信のコミット */ プライベート 関数 コミット() { $this->dbh->commit(); }
/** * ロールバック トランザクションのロールバック */ プライベート 関数 rollback() { $this- >dbh->rollback(); }
/** * トランザクション トランザクションを通じて複数の SQL ステートメントを処理します */ public 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 指定されたフィールドが指定されたデータテーブルに存在するかどうかを確認します */ private function checkFields($table, $arrayFields) { $fields = $this->getFields($table); foreach ($arrayFields as $key => $value) { if (!in_array($key, $fields)) { $this->outputError("フィールドリストの不明な列 `$key` "); } } } /***/ プライベート 関数 getFields($table) { $fields = array(); $recordset= $this->dbh->query("SHOW COLUMNS FROM $table"); $これ- >getPDOError(); $recordset->setFetchMode(PDO::FETCH_ASSOC); $result = $recordset->fetchAll(); foreach ($result as $rows) { $fields [] = $rows['フィールド']; } return $fields; }
/** * getPDOError PDO エラー情報を取得します */ private function getPDOError( ) { if ($ this->dbh->errorCode() != '00000') { $arrayError = $this->dbh->errorInfo(); $this->outputError($arrayError[2] ); } }
/** * デバッグ * * @param mixed $debuginfo */ プライベート関数 debug($debuginfo) { var _dump($debuginfo); exit(); }
/** * 出力エラーメッセージ */ プライベート 関数 outputError($strErrMsg) { throw new Exception('MySQL Error: '.$strErrMsg); }
/** * 破壊 データベース接続を閉じる */ public function destruct() { $this->dbh = null; } } ?>
|
以上がPHP シングルトン モードの利点の分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。