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 相关文章推荐
BBS(php &amp; mysql)完整版(七)
Oct 09 PHP
PHP读取MySQL数据代码
Jun 05 PHP
PHP autoload与spl_autoload自动加载机制的深入理解
Jun 05 PHP
php实现可以设置中奖概率的抽奖程序代码分享
Jan 19 PHP
PHP会话控制:Session与Cookie详解
Sep 27 PHP
8个PHP数组面试题
Jun 23 PHP
PHP简单处理表单输入的特殊字符的方法
Feb 03 PHP
Yii框架组件和事件行为管理详解
May 20 PHP
php 判断过去离现在几年的函数(实例代码)
Nov 15 PHP
浅谈php中变量的数据类型判断函数
Mar 04 PHP
解决Laravel无法使用COOKIE和SESSION的问题
Oct 16 PHP
php实现对短信验证码发送次数的限制实例讲解
Mar 04 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学习之PHP表达式
2006/10/09 PHP
php获取用户浏览器版本的方法
2015/01/03 PHP
Yii编程开发常见调用技巧集锦
2016/07/15 PHP
微信支付之JSAPI公众号支付详解
2019/05/15 PHP
js判断浏览器的比较全的代码
2007/02/13 Javascript
List Installed Hot Fixes
2007/06/12 Javascript
js模仿hover的具体实现代码
2013/12/30 Javascript
JS截取url中问号后面参数的值信息
2014/04/29 Javascript
JavaScript中的值是按值传递还是按引用传递问题探讨
2015/01/30 Javascript
详解Wondows下Node.js使用MongoDB的环境配置
2016/03/01 Javascript
详解AngularJS中ng-src指令的使用
2016/09/07 Javascript
Bootstrap3多级下拉菜单
2017/02/24 Javascript
Angular2仿照微信UI实现9张图片上传和预览的示例代码
2017/10/19 Javascript
基于Require.js使用方法(总结)
2017/10/26 Javascript
[50:17]Newbee vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
python获取当前用户的主目录路径方法(推荐)
2017/01/12 Python
对numpy 数组和矩阵的乘法的进一步理解
2018/04/04 Python
对Python字符串中的换行符和制表符介绍
2018/05/03 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
2019/05/10 Python
Python 写入训练日志文件并控制台输出解析
2019/08/13 Python
python之yield和Generator深入解析
2019/09/18 Python
利用python Selenium实现自动登陆京东签到领金币功能
2019/10/31 Python
pytorch sampler对数据进行采样的实现
2019/12/31 Python
CSS3 please 跨浏览器的CSS3产生器
2010/03/14 HTML / CSS
HTML5探秘:用requestAnimationFrame优化Web动画
2018/06/03 HTML / CSS
加拿大票务网站:Ticketmaster加拿大
2017/07/17 全球购物
英国旅游额外服务市场领导者:Holiday Extras(机场停车场、酒店、接送等)
2017/10/07 全球购物
SIDESTEP荷兰:在线购买鞋子
2019/11/18 全球购物
俄罗斯香水和化妆品网上商店:NOTINO.ru
2019/12/17 全球购物
办公室驾驶员岗位职责
2013/11/15 职场文书
建筑个人求职信范文
2014/01/25 职场文书
个人优缺点自我评价
2014/01/27 职场文书
服装店营销方案
2014/03/10 职场文书
二手房买卖协议书
2014/04/10 职场文书
党员干部作风建设思想汇报范文
2014/10/25 职场文书
mysql 子查询的使用
2022/04/28 MySQL