PHP用单例模式实现一个数据库类
使用单例模式的出发点:
1、php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源。
2、如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分。
3、在一次页面请求中, 便于进行调试, 因为所有的代码(例如数据库操作类db)都集中在一个类中, 我们可以在类中设置钩子, 输出日志,从而避免到处var_dump, echo。
创造单例注意:
1、一个雷只能有一个类对象(只能实例化一个对象)
2、它必须自己创建这个实例
3、它必须自行向整个系统提供这个实例
4、构造函数和克隆函数必须声明为私有的,这是为了防止外部程序 new 类从而失去单例模式的意义
5、 getInstance()方法必须声明为公有的,必须调用此方法以返回唯一实例的一个引用
6、拥有一个保存类的实例的静态成员变量
7、PHP的单例模式是相对而言的,因为PHP的解释运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收
8、拥有一个访问这个实例的公共的静态方法(常用getInstance()方法进行实例化单例类,通过instanceof操作符可以检测到类是否已经被实例化)
另外,需要创建__clone()方法防止对象被复制(克隆)
代码如下:
<?php
class Danli
{ //保存类实例的静态成员变量
private static $_instance; //private标记的构造方法
private function __construct()
{
echo 'This is a Constructed method;';
} //创建__clone方法防止对象被复制克隆
public function __clone()
{
trigger_error('Clone is not allow!', E_USER_ERROR);
} //单例方法,用于访问实例的公共的静态方法
public static function getInstance()
{
if (!(self::$_instance instanceof self)) {
self::$_instance = new self;
}
return self::$_instance;
} public function test()
{
echo '调用方法成功';
} } /*用new实例化private标记构造函数的类会报错
$danli = new Danli(); 复制(克隆)对象将导致一个E_USER_ERROR
$danli_clone = clone $danli;
*/ //正确方法,用双冒号::操作符访问静态方法获取实例
$danli = Danli::getInstance();
$danli->test();
?>
运用单例模式实现一个数据库类:
<?php
class DBHelper
{
private $link;
static private $_instance; // 连接数据库
private function __construct($host, $username, $password)
{
$this->link = mysql_connect($host, $username, $password);
$this->query("SET NAMES 'utf8'", $this->link);
//echo mysql_errno($this->link) . ": " . mysql_error($link). "n";
//var_dump($this->link);
return $this->link;
}
private function __clone()
{
}
public static function get_class_nmdb($host, $username, $password)
{
//$connector = new nmdb($host, $username, $password);
//return $connector; if (FALSE == (self::$_instance instanceof self)) {
self::$_instance = new self($host, $username, $password);
}
return self::$_instance;
}
// 连接数据表
public function select_db($database)
{
$this->result = mysql_select_db($database);
return $this->result;
}
// 执行SQL语句
public function query($query)
{
return $this->result = mysql_query($query, $this->link);
}
// 将结果集保存为数组
public function fetch_array($fetch_array)
{
return $this->result = mysql_fetch_array($fetch_array, MYSQL_ASSOC);
}
// 获得记录数目
public function num_rows($query)
{
return $this->result = mysql_num_rows($query);
}
// 关闭数据库连接
public function close()
{
return $this->result = mysql_close($this->link);
}
}
$connector = DBHelper::get_class_nmdb($host, $username, $password);
$connector -> select_db($database);
?>
也可以参考这个类实现:
<?php
/*
* mysql 单例
*/
class mysql{
private $host ='localhost'; //数据库主机
private $user = 'root'; //数据库用户名
private $pwd = ''; //数据库用户名密码
private $database = 'imoro_imoro'; //数据库名
private $charset = 'utf8'; //数据库编码,GBK,UTF8,gb2312
private $link; //数据库连接标识;
private $rows; //查询获取的多行数组
static $_instance; //存储对象
/**
* 构造函数
* 私有
*/
private function __construct($pconnect = false) {
if (!$pconnect) {
$this->link = @ mysql_connect($this->host, $this->user, $this->pwd) or $this->err();
} else {
$this->link = @ mysql_pconnect($this->host, $this->user, $this->pwd) or $this->err();
}
mysql_select_db($this->database) or $this->err();
$this->query("SET NAMES '{$this->charset}'", $this->link);
return $this->link;
}
/**
* 防止被克隆
*
*/
private function __clone(){}
public static function getInstance($pconnect = false){
if(FALSE == (self::$_instance instanceof self)){
self::$_instance = new self($pconnect);
}
return self::$_instance;
}
/**
* 查询
*/
public function query($sql, $link = '') {
$this->result = mysql_query($sql, $this->link) or $this->err($sql);
return $this->result;
}
/**
* 单行记录
*/
public function getRow($sql, $type = MYSQL_ASSOC) {
$result = $this->query($sql);
return @ mysql_fetch_array($result, $type);
}
/**
* 多行记录
*/
public function getRows($sql, $type = MYSQL_ASSOC) {
$result = $this->query($sql);
while ($row = @ mysql_fetch_array($result, $type)) {
$this->rows[] = $row;
}
return $this->rows;
}
/**
* 错误信息输出
*/
protected function err($sql = null) {
//这里输出错误信息
echo 'error';
exit();
}
}
//用例
$db = mysql::getInstance();
$db2 = mysql::getInstance();
$data = $db->getRows('select * from blog');
//print_r($data);
//判断两个对象是否相等
if($db === $db2){
echo 'true';
}
?>
PHP单例模式的缺点
众所周知,PHP语言是一种解释型的脚本语言,这种运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收。也就是说,PHP在语言级别上没有办法让某个对象常驻内存,这和asp.net、Java等编译型是不同的,比如在Java中单例会一直存在于整个应用程序的生命周期里,变量是跨页面级
的,真正可以做到这个实例在应用程序生命周期中的唯一性。然而在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面
级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的。
PHP用单例模式实现一个数据库类的更多相关文章
- Python一个简单的数据库类封装
#encoding:utf-8 #name:mod_db.py '''使用方法:1.在主程序中先实例化DB Mysql数据库操作类. 2.使用方法:db=database() db.fet ...
- 一个数据库操作类,适用于Oracle,ACCESS,SQLSERVER
最近做了一个数据诊断的项目,里面自己写了一个数据库的操作类,包含:连接数据库.读数据表.执行SQL操作,释放数据库等组成,希望对大家有用,由于水平有限,若有错误或者代码不足地方欢迎指正,谢谢. ADO ...
- 利用单例模式设计数据库连接Model类
之前在<[php]利用php的构造函数与析构函数编写Mysql数据库查询类>(点击打开链接)写过的Mysql数据库查询类还不够完美,利用<[Java]单例模式>(点击打开链接) ...
- mssqlserver数据导出到另外一个数据库
mssqlserver数据导出到另外一个数据库 准备源数据库,找到想要导出的数据库,右键选择"任务"再选择"导出数据" 设置源数据库信息 3.设置目标数据库,导 ...
- dede数据库类使用方法 $dsql
dedecms的数据库操作类,非常实用,在二次开发中尤其重要,这个数据库操作类说明算是奉献给大家的小礼物了. 引入common.inc.php文件 require_once (dirname(__FI ...
- Dedesql数据库类详解
今天花点时间讲解下织梦的sql数据库类,近期本来是准备录制一套视频教程的,但由于视频压缩的问题迟迟没有开展工作,如果大家有什么好的视频压缩方式可以通过邮件的方式告诉我:tianya#dedecms.c ...
- dede 数据库类使用列表
dedecms的数据库操作类,非常实用,在二次开发中尤其重要,这个数据库操作类说明算是奉献给大家的小礼物了. 引入common.inc.php文件 require_once (dirname(__FI ...
- cookiecutter-flask生成的框架里边自带了一个CRUDMixin类
单元测试的必要性 之前曾经写过一篇讲单元测试的,正好最近也在实践和摸索.我似乎有种洁癖,就是我会严格遵守流程性的东西,比如测试,注释和文档等.目前就职的公司在我接手项目的时候是没有一行单元测试的,我挺 ...
- dede数据库类使用方法$dsql【转】
http://www.cnblogs.com/xcxc/p/3601909.html dedecms的数据库操作类,非常实用,在二次开发中尤其重要,这个数据库操作类说明算是奉献给大家的小礼物了. 引入 ...
随机推荐
- 菜鸟学Struts2——零配置(Convention )
又是周末,继续Struts2的学习,之前学习了,Struts的原理,Actions以及Results,今天对对Struts的Convention Plugin进行学习,如下图: Struts Conv ...
- JavaScript Array对象
介绍Js的Array 数组对象. 目录 1. 介绍:介绍 Array 数组对象的说明.定义方式以及属性. 2. 实例方法:介绍 Array 对象的实例方法:concat.every.filter.fo ...
- .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...
- 要想提高PHP的编程效率,你必须知道的要点
1.当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数.此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储 ...
- 代码的坏味道(18)——依恋情结(Feature Envy)
坏味道--依恋情结(Feature Envy) 特征 一个函数访问其它对象的数据比访问自己的数据更多. 问题原因 这种气味可能发生在字段移动到数据类之后.如果是这种情况,你可能想将数据类的操作移动到这 ...
- JavaWeb——ServletContext
一.基本概念 说起ServletContext,一些人会产生误解,以为一个servlet对应一个ServletContext.其实不是这样的,事实是一个web应用对应一个ServletContext, ...
- GOF23设计模式之单例模式
·核心作用: -保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. ·常见应用场景: -Windows的Task Manager(任务管理器)就是很典型的单例模式 -Windows的Recy ...
- 【干货分享】流程DEMO-事务呈批表
流程名: 事务呈批表 业务描述: 办公采购.会议费用等事务的申请.流程发起时,会检查预算,如果预算不够,将不允许发起费用申请,如果预算够用,将发起流程,同时占用相应金额的预算,但撤销流程会释放相应金 ...
- BPM生产安全管理解决方案分享
一.方案概述生产安全管理是企业生产管理的重要组成部分,组织实施好企业安全管理规划.指导.检查和决策,保证生产处于最佳安全状态是安全管理的重要内容和职责.H3 BPM企业生产安全管理解决方案是一套专门为 ...
- Android中常见的图片加载框架
图片加载涉及到图片的缓存.图片的处理.图片的显示等.而随着市面上手机设备的硬件水平飞速发展,对图片的显示要求越来越高,稍微处理不好就会造成内存溢出等问题.很多软件厂家的通用做法就是借用第三方的框架进行 ...