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的数据库操作类,非常实用,在二次开发中尤其重要,这个数据库操作类说明算是奉献给大家的小礼物了. 引入 ...
随机推荐
- Java多线程
一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程 ...
- JSON.parse()和JSON.stringify()
1.parse 用于从一个字符串中解析出json 对象.例如 var str='{"name":"cpf","age":"23&q ...
- 基于OpenCV的车辆检测与追踪的实现
最近老师布置了一个作业,是做一个基于视频的车辆检测与追踪,用了大概两周的时间做了一个简单的,效果不是很理想,但抑制不住想把自己的一些认识写下来,这里就把一些网络上的博客整理一下分享给大家,希望帮助到大 ...
- 【原】AFNetworking源码阅读(二)
[原]AFNetworking源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中我们在iOS Example代码中提到了AFHTTPSessionMa ...
- 深究标准IO的缓存
前言 在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?今天早上爬起来赶紧找了 ...
- Android和JavaScript相互调用的方法
转载地址:http://www.jb51.net/article/77206.htm 这篇文章主要介绍了Android和JavaScript相互调用的方法,实例分析了Android的WebView执行 ...
- npm package.json属性详解
概述 本文档是自己看官方文档的理解+翻译,内容是package.json配置里边的属性含义.package.json必须是一个严格的json文件,而不仅仅是js里边的一个对象.其中很多属性可以通过np ...
- 利用Node.js的Net模块实现一个命令行多人聊天室
1.net模块基本API 要使用Node.js的net模块实现一个命令行聊天室,就必须先了解NET模块的API使用.NET模块API分为两大类:Server和Socket类.工厂方法. Server类 ...
- 理解 .NET Platform Standard
相关博文:ASP.NET 5 Target framework dnx451 and dnxcore50 .NET Platform Standard:https://github.com/dotne ...
- submit text3常用快捷键
在网上找了一些submit text的快捷键: Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑)Ctrl+G 跳转到相应的行Ctrl+J 合并行(已选择需要合并的 ...