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的数据库操作类,非常实用,在二次开发中尤其重要,这个数据库操作类说明算是奉献给大家的小礼物了. 引入 ...
随机推荐
- HTTPS 互联网世界的安全基础
近一年公司在努力推进全站的 HTTPS 化,作为负责应用系统的我们,在配合这个趋势的过程中,顺便也就想去搞清楚 HTTP 后面的这个 S 到底是个什么含义?有什么作用?带来了哪些影响?毕竟以前也就只是 ...
- Android消息传递之基于RxJava实现一个EventBus - RxBus
前言: 上篇文章学习了Android事件总线管理开源框架EventBus,EventBus的出现大大降低了开发成本以及开发难度,今天我们就利用目前大红大紫的RxJava来实现一下类似EventBus事 ...
- 关于 CSS 反射倒影的研究思考
原文地址:https://css-tricks.com/state-css-reflections 译者:nzbin 友情提示:由于演示 demo 的兼容性,推荐火狐浏览.该文章篇幅较长,内容庞杂,有 ...
- JDBC简介
jdbc连接数据库的四个对象 DriverManager 驱动类 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 ...
- arcgis api for js入门开发系列六地图分屏对比(含源代码)
上一篇实现了demo的地图标绘模块,本篇新增地图地图分屏对比模块,截图如下(源代码见文章底部): 对效果图的简单介绍一下,在demo只采用了两分屏对比,感兴趣的话,可以在两分屏的基础上拓展,修改css ...
- linux下使用shell 自动执行脚本文件
以下实例本人在Centos6.5 64位操作系统中使用 一.定时复制文件 a.在/usr/local/wfjb_web_back目录下创建 tomcatBack.sh文件 文件内容: #将tomcat ...
- Linux下的C Socket编程 -- server端的继续研究
Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...
- 玩转Windows服务系列汇总
玩转Windows服务系列汇总 创建Windows服务 Debug.Release版本的注册和卸载及其原理 无COM接口Windows服务启动失败原因及解决方案 服务运行.停止流程浅析 Windows ...
- [Intel Edison开发板] 02、Edison开发板入门
一.前言 Start from the link: 开始学习的链接 上面链接是官网的教程,按照教程可以开发板入门: 其中第一步是了解开发板,涉及到如何组装.如何连线.一些主要的接口简单介绍等信息: 第 ...
- ASP.NET MVC 视图(三)
ASP.NET MVC 视图(三) 前言 上篇对于Razor视图引擎和视图的类型做了大概的讲解,想必大家对视图的本身也有所了解,本篇将利用IoC框架对视图的实现进行依赖注入,在此过程过会让大家更了解的 ...