ホームページ >バックエンド開発 >PHPチュートリアル >PHPでシングルトンパターンを実装する方法

PHPでシングルトンパターンを実装する方法

小云云
小云云オリジナル
2017-12-01 11:01:182412ブラウズ

この記事では、PHP でシングルトン モードを実装する方法と、シングルトン モードを使用する理由について説明します。興味のある方は参考にしてください。

1. シングルトンパターンとは何ですか?
1. 意味
オブジェクト作成パターンとして、シングルトン パターンは、クラスがインスタンスを 1 つだけ持つことを保証し、クラス自体をインスタンス化し、このインスタンスをシステム全体にグローバルに提供します。インスタンスのコピーは作成されませんが、シングルトン クラス内に格納されているインスタンスへの参照を返します。
2. シングルトン モードの 3 つの重要なポイント:
(1)。 クラスの唯一のインスタンスを保持する静的メンバー変数が必要です:
private static $_instance
(2)。 コンストラクターとクローン関数は、新しいクラスからの外部プログラムを防止し、シングルトン モードの意味を失うために、プライベートとして宣言する必要があります:

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


(3) このインスタンスにアクセスするための public static メソッド (通常は getInstance) を提供する必要があります。メソッド ) を使用して、唯一のインスタンスへの参照を返します

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


2. なぜシングルトン パターンを使用するのでしょうか?
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 操作データベース クラスのカプセル化です。


呼び出しメソッド:

<?php
/**
 * MyPDO
 */
class MyPDO
{
  protected static $_instance = null;
  protected $dbName = &#39;&#39;;
  protected $dsn;
  protected $dbh;
    
  /**
   * 构造
   * 
   * @return MyPDO
   */
  private function __construct($dbHost, $dbUser, $dbPasswd, $dbName, $dbCharset)
  {
    try {
      $this->dsn = &#39;mysql:host=&#39;.$dbHost.&#39;;dbname=&#39;.$dbName;
      $this->dbh = new PDO($this->dsn, $dbUser, $dbPasswd);
      $this->dbh->exec(&#39;SET character_set_connection=&#39;.$dbCharset.&#39;, character_set_results=&#39;.$dbCharset.&#39;, character_set_client=binary&#39;);
    } 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 = &#39;All&#39;, $debug = false)
  {
    if ($debug === true) $this->debug($strSql);
    $recordset = $this->dbh->query($strSql);
    $this->getPDOError();
    if ($recordset) {
      $recordset->setFetchMode(PDO::FETCH_ASSOC);
      if ($queryMode == &#39;All&#39;) {
        $result = $recordset->fetchAll();
      } elseif ($queryMode == &#39;Row&#39;) {
        $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 = &#39;&#39;, $debug = false)
  {
    $this->checkFields($table, $arrayDataValue);
    if ($where) {
      $strSql = &#39;&#39;;
      foreach ($arrayDataValue as $key => $value) {
        $strSql .= ", `$key`=&#39;$value&#39;";
      }
      $strSql = substr($strSql, 1);
      $strSql = "UPDATE `$table` SET $strSql WHERE $where";
    } else {
      $strSql = "REPLACE INTO `$table` (`".implode(&#39;`,`&#39;, array_keys($arrayDataValue))."`) VALUES (&#39;".implode("&#39;,&#39;", $arrayDataValue)."&#39;)";
    }
    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(&#39;`,`&#39;, array_keys($arrayDataValue))."`) VALUES (&#39;".implode("&#39;,&#39;", $arrayDataValue)."&#39;)";
    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(&#39;`,`&#39;, array_keys($arrayDataValue))."`) VALUES (&#39;".implode("&#39;,&#39;", $arrayDataValue)."&#39;)";
    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 = &#39;&#39;, $debug = false)
  {
    if ($where == &#39;&#39;) {
      $this->outputError("&#39;WHERE&#39; 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 = &#39;&#39;, $debug = false)
  {
    $strSql = "SELECT MAX(".$field_name.") AS MAX_VALUE FROM $table";
    if ($where != &#39;&#39;) $strSql .= " WHERE $where";
    if ($debug === true) $this->debug($strSql);
    $arrTemp = $this->query($strSql, &#39;Row&#39;);
    $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 = &#39;&#39;, $debug = false)
  {
    $strSql = "SELECT COUNT($field_name) AS NUM FROM $table";
    if ($where != &#39;&#39;) $strSql .= " WHERE $where";
    if ($debug === true) $this->debug($strSql);
    $arrTemp = $this->query($strSql, &#39;Row&#39;);
    return $arrTemp[&#39;NUM&#39;];
  }
    
  /**
   * 获取表引擎
   * 
   * @param String $dbName 库名
   * @param String $tableName 表名
   * @param Boolean $debug
   * @return String
   */
  public function getTableEngine($dbName, $tableName)
  {
    $strSql = "SHOW TABLE STATUS FROM $dbName WHERE Name=&#39;".$tableName."&#39;";
    $arrayTableInfo = $this->query($strSql);
    $this->getPDOError();
    return $arrayTableInfo[0][&#39;Engine&#39;];
  }
    
  /**
   * 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[&#39;Field&#39;];
    }
    return $fields;
  }
    
  /**
   * getPDOError 捕获PDO错误信息
   */
  private function getPDOError()
  {
    if ($this->dbh->errorCode() != &#39;00000&#39;) {
      $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(&#39;MySQL Error: &#39;.$strErrMsg);
  }
    
  /**
   * destruct 关闭数据库连接
   */
  public function destruct()
  {
    $this->dbh = null;
  }
}
?>

上記の内容は、PHPでシングルトンモードを実装する方法についてです。皆さんのお役に立てれば幸いです。

関連する推奨事項:

わかりやすいPHPデザインパターンシングルトンパターン

PHPデザインパターンにおけるファクトリーパターンとシングルトンパターンの違い

PHPデザインパターンにおけるシングルトンパターンの分析

以上がPHPでシングルトンパターンを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。