PHP单例模式应用示例【多次连接数据库只实例化一次】


Posted in PHP onDecember 18, 2018

本文实例讲述了PHP单例模式应用。分享给大家供大家参考,具体如下:

以前刚开始工作的时候经常连接数据库,每次用到数据库的时候就要用new进行实例并连接一次,当时因为连接数据库的次数不是很频繁,所以也没什么。后来主管对我说我现在这样每次都连接数据库的如果数据读取频繁的话对数据库和系统造成的压力会很大,让我想想办法能不能就连接一次数据库然后再次用到的时候就不用new一个新的连接了,当时怎么也没想到好的办法,知道最近学到了单例模式才恍然大悟,当时主管是引导我用单例模式的,只怪我以前对开发模式不懂。好了废话少说,下面来看单例模式:

单例模式(职责模式):

简单的说,一个对象(在学习设计模式之前,需要比较了解面向对象思想)只负责一个特定的任务;

单例类:

1、构造函数需要标记为private(访问控制:防止外部代码使用new操作符创建对象),单例类不能在其他类中实例化,只能被其自身实例化;

2、拥有一个保存类的实例的静态成员变量

3、拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)

另外,需要创建__clone()方法防止对象被复制(克隆)

为什么要使用PHP单例模式?

1、php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源。

2、如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。

3、在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo

代码(官方文档中的):

<?php
class Singletons{
  // 保存类实例在此属性中
  private static $instance;
  // 构造方法声明为private,防止直接创建对象
  private function __construct()
  {
    echo 'Iam constructed';
  }
  // singleton 方法
  public static function singleton()
  {
    if (!isset(self::$instance)) {
      $c = __CLASS__;
      self::$instance =new$c;
    }
    return self::$instance;
  }
  // Example类中的普通方法
  public function bark()
  {
    echo 'Woof!';
  }
  // 阻止用户复制对象实例
  public function __clone()
  {
    trigger_error('Clone is not allowed.',E_USER_ERROR);
  }
}//endclass singletons
  //这个写法会出错,因为构造方法被声明为private
  //$test= new Singletons();
  // 下面将得到Example类的单例对象
  $test= Singletons::singleton();
  $test->bark();
  // 复制对象将导致一个E_USER_ERROR.
  $test_clone= clone $test;
?>

结果:

I am constructed!   Woof!
Fatal error:
Clone is not allowed. in E:\APMServ5.2.6\www\htdocs\Lee\myprogram\other\class\singletons.phpon line 31

以下内容源自网络(可以参考学习一下):

单例模式的三个要点:

(1). 需要一个保存类的唯一实例的静态成员变量:

 

private static $_instance;

(2). 构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义:

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;
}

二、为什么要使用单例模式?

1、PHP缺点:

PHP语言是一种解释型的脚本语言,这种运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收。也就是说,PHP在语言级别上没有办法让某个对象常驻内存,这和asp.NET、Java等编译型是不同的,比如在Java中单例会一直存在于整个应用程序的生命周期里,变量是跨页面级的,真正可以做到这个实例在应用程序生命周期中的唯一性。然而在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的。

2、单例模式在PHP中的应用场合:

(1)、应用程序与数据库交互

一个应用中会存在大量的数据库操作,比如过数据库句柄来连接数据库这一行为,使用单例模式可以避免大量的new操作,因为每一次new操作都会消耗内存资源和系统资源。

(2)、控制配置信息

如果系统中需要有一个类来全局控制某些配置信息,那么使用单例模式可以很方便的实现.

三、如何实现单例模式?

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

3、深入理解

<?php
 class db {
   public $conn;
   public static $sql;
   public static $instance=null;
   private function __construct(){
     require_once('db.config.php');
     $this->conn = mysql_connect($db['host'],$db['user'],$db['password']);
     if(!mysql_select_db($db['database'],$this->conn)){
      echo "失败";
    };
    mysql_query('set names utf8',$this->conn);
  }
  public static function getInstance(){
    if(is_null(self::$instance)){
      self::$instance = new db;
    }
    return self::$instance;
  }
  /**
   * 查询数据库
   */
  public function select($table,$condition=array(),$field = array()){
    $where='';
    if(!empty($condition)){
      foreach($condition as $k=>$v){
        $where.=$k."='".$v."' and ";
      }
      $where='where '.$where .'1=1';
    }
    $fieldstr = '';
    if(!empty($field)){
      foreach($field as $k=>$v){
        $fieldstr.= $v.',';
      }
       $fieldstr = rtrim($fieldstr,',');
    }else{
      $fieldstr = '*';
    }
    self::$sql = "select {$fieldstr} from {$table} {$where}";
    $result=mysql_query(self::$sql,$this->conn);
    $resuleRow = array();
    $i = 0;
    while($row=mysql_fetch_assoc($result)){
      foreach($row as $k=>$v){
        $resuleRow[$i][$k] = $v;
      }
      $i++;
    }
    return $resuleRow;
  }
  /**
   * 添加一条记录
   */
   public function insert($table,$data){
    $values = '';
    $datas = '';
    foreach($data as $k=>$v){
      $values.=$k.',';
      $datas.="'$v'".',';
    }
    $values = rtrim($values,',');
    $datas  = rtrim($datas,',');
    self::$sql = "INSERT INTO {$table} ({$values}) VALUES ({$datas})";
    if(mysql_query(self::$sql)){
      return mysql_insert_id();
    }else{
      return false;
    };
   }
   /**
   * 修改一条记录
   */
  public function update($table,$data,$condition=array()){
    $where='';
    if(!empty($condition)){
      foreach($condition as $k=>$v){
        $where.=$k."='".$v."' and ";
      }
      $where='where '.$where .'1=1';
    }
    $updatastr = '';
    if(!empty($data)){
      foreach($data as $k=>$v){
        $updatastr.= $k."='".$v."',";
      }
      $updatastr = 'set '.rtrim($updatastr,',');
    }
    self::$sql = "update {$table} {$updatastr} {$where}";
    return mysql_query(self::$sql);
  }
  /**
   * 删除记录
   */
   public function delete($table,$condition){
    $where='';
    if(!empty($condition)){
      foreach($condition as $k=>$v){
        $where.=$k."='".$v."' and ";
      }
      $where='where '.$where .'1=1';
    }
    self::$sql = "delete from {$table} {$where}";
    return mysql_query(self::$sql);
   }
  public static function getLastSql(){
    echo self::$sql;
  }
}
$db = db::getInstance();
//$list = $db->select('demo',array('name'=>'tom','password'=>'ds'),array('name','password'));
//echo $db->insert('demo',array('name'=>'最近你啦','password'=>'123'));
//echo $db->update('demo',array("name"=>'xxx',"password"=>'123'),array('id'=>1));
echo $db->delete('demo',array('id'=>'2'));
db::getLastSql();
echo "<pre>";
?>

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
dedecms后台验证码总提示错误的解决方法
Mar 21 PHP
几款免费开源的不用数据库的php的cms
Dec 19 PHP
php中使用Akismet防止垃圾评论的代码
Jun 10 PHP
浅析echo(),print(),print_r(),return之间的区别
Nov 27 PHP
ThinkPHP分页类使用详解
Mar 05 PHP
typecho插件编写教程(四):插件挂载
May 28 PHP
thinkphp配置文件路径的实现方法
Aug 30 PHP
php根据年月获取当月天数及日期数组的方法
Nov 30 PHP
基于php编程规范(详解)
Aug 17 PHP
php微信开发之关键词回复功能
Jun 13 PHP
TP5(thinkPHP框架)实现后台清除缓存功能示例
May 29 PHP
laravel实现上传图片并在页面显示的例子
Oct 14 PHP
PHP时间戳和日期相互转换操作实例小结
Dec 18 #PHP
PHP获取星期几的常用方法小结
Dec 18 #PHP
php往mysql中批量插入数据实例教程
Dec 12 #PHP
yii2 url重写并隐藏index.php方法
Dec 10 #PHP
php 处理png图片白色背景色改为透明色的实例代码
Dec 10 #PHP
php高清晰度无损图片压缩功能的实现代码
Dec 09 #PHP
PHP聊天室简单实现方法详解
Dec 08 #PHP
You might like
十大催泪虐心动漫,你能坚持看到第几部?
2020/03/04 日漫
提升PHP执行速度全攻略(上)
2006/10/09 PHP
paypal即时到账php实现代码
2010/11/28 PHP
深入解析Session是否必须依赖Cookie
2013/08/02 PHP
php把session写入数据库示例
2014/02/26 PHP
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
详解Yii2 定制表单输入字段的标签和样式
2017/01/04 PHP
jQuery学习2 选择器的使用说明
2010/02/07 Javascript
JavaScript 精粹读书笔记(1,2)
2010/02/07 Javascript
让angularjs支持浏览器自动填表
2014/11/10 Javascript
基于JavaScript实现通用tab选项卡(通用性强)
2016/01/07 Javascript
jQuery解决input元素的blur事件和其他非表单元素的click事件冲突问题
2016/08/15 Javascript
domReady的实现案例
2016/11/23 Javascript
jquery中绑定事件的异同
2017/02/28 Javascript
vue中的ref和$refs的使用
2018/11/22 Javascript
react 移动端实现列表左滑删除的示例代码
2019/07/04 Javascript
如何在微信小程序中使用骨架屏的步骤
2020/06/12 Javascript
[01:06:54]DOTA2-DPC中国联赛 正赛 SAG vs DLG BO3 第二场 2月28日
2021/03/11 DOTA
一个计算身份证号码校验位的Python小程序
2014/08/15 Python
python之virtualenv的简单使用方法(必看篇)
2017/11/25 Python
pandas factorize实现将字符串特征转化为数字特征
2019/12/19 Python
Python使用pyexecjs代码案例解析
2020/07/13 Python
Python DES加密实现原理及实例解析
2020/07/17 Python
python使用yaml 管理selenium元素的示例
2020/12/01 Python
美国知名珠宝首饰品牌:Gemvara
2017/10/06 全球购物
购买原创艺术品:Zatista
2019/11/09 全球购物
瑞典多品牌连锁店:Johnells
2021/01/13 全球购物
高中英语演讲稿范文
2014/04/24 职场文书
啦啦队口号大全
2014/06/16 职场文书
岗位工作说明书
2014/07/29 职场文书
法定代表人授权委托书范文
2014/09/22 职场文书
导游词之江南周庄
2019/12/06 职场文书
Django项目如何正确配置日志(logging)
2021/04/29 Python
为什么MySQL 删除表数据 磁盘空间还一直被占用
2021/10/16 MySQL
Python实现灰色关联分析与结果可视化的详细代码
2022/03/25 Python
集英社今正式宣布 成立游戏公司“集英社Games”
2022/03/31 其他游戏