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 相关文章推荐
使用apache模块rewrite_module (转)
Feb 14 PHP
PHP字符串 ==比较运算符的副作用
Oct 21 PHP
超级简单的php+mysql留言本源码
Nov 11 PHP
curl不使用文件存取cookie php使用curl获取cookie示例
Jan 26 PHP
smarty表格换行实例
Dec 15 PHP
WordPress中访客登陆实现邮件提醒的PHP脚本实例分享
Dec 14 PHP
PHP扩展迁移为PHP7扩展兼容性问题记录
Feb 15 PHP
PHP函数rtrim()使用中的怪异现象分析
Feb 24 PHP
PHP简单实现解析xml为数组的方法
May 02 PHP
thinkPHP5.0框架事务处理操作简单示例
Sep 07 PHP
PHP7内核CGI与FastCGI详解
Apr 14 PHP
phpfpm的作用和用法
Oct 10 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
PHP中用header图片地址 简单隐藏图片源地址
2008/04/09 PHP
php 常用类汇总 推荐收藏
2010/05/13 PHP
php中将网址转换为超链接的函数
2011/09/02 PHP
PHP中的流(streams)浅析
2015/07/02 PHP
php+mysql查询实现无限下级分类树输出示例
2016/10/03 PHP
在Laravel中使用GuzzleHttp调用第三方服务的API接口代码
2019/10/15 PHP
js 事件小结 表格区别
2007/08/13 Javascript
解决jquery的.animate()函数在IE6下的问题
2010/12/03 Javascript
JavaScript代码简单实现求杨辉三角给定行的最大值
2013/10/29 Javascript
使用jQuery实现图片遮罩半透明坠落遮挡
2015/03/16 Javascript
javascript实现简单的省市区三级联动
2015/05/14 Javascript
基于JS实现简单的样式切换效果代码
2015/09/04 Javascript
Javascript农历与公历相互转换的简单实例
2016/10/09 Javascript
解决angularjs service中依赖注入$scope报错的问题
2018/10/02 Javascript
使用p5.js实现动态GIF图片临摹重现
2019/10/23 Javascript
jQuery实现的图片点击放大缩小功能案例
2020/01/02 jQuery
Vue-cli打包后部署到子目录下的路径问题说明
2020/09/02 Javascript
python爬虫框架talonspider简单介绍
2017/06/09 Python
详解Python list 与 NumPy.ndarry 切片之间的对比
2017/07/24 Python
python利用urllib和urllib2访问http的GET/POST详解
2017/09/27 Python
python爬虫headers设置后无效的解决方法
2017/10/21 Python
numpy.random.seed()的使用实例解析
2018/02/03 Python
flask入门之文件上传与邮件发送示例
2018/07/18 Python
Python Django简单实现session登录注销过程详解
2019/08/06 Python
使用Python串口实时显示数据并绘图的例子
2019/12/26 Python
python对文件的操作方法汇总
2020/02/28 Python
Django使用list对单个或者多个字段求values值实例
2020/03/31 Python
PyTorch实现重写/改写Dataset并载入Dataloader
2020/07/14 Python
通俗易懂了解Python装饰器原理
2020/09/17 Python
欧洲最大的笔和书写专家:The Pen Shop
2017/03/19 全球购物
新西兰便宜隐形眼镜购买网站:QUICKLENS New Zealand
2019/03/02 全球购物
Stuarts London美国/加拿大:世界领先的独立男装零售商之一
2019/03/18 全球购物
《陋室铭》教学反思
2014/02/26 职场文书
晚会开场白和结束语
2015/05/29 职场文书
2015年机关作风和效能建设工作总结
2015/07/23 职场文书
Python3 使用pip安装git并获取Yahoo金融数据的操作
2021/04/08 Python