单例:
一个类只能有一个对象
应用场景:多次请求数据库只需要一个连接对象。
实现:三私一公
1、私有的静态属性用来保存对象的单例
2、私有的构造方法用来阻止在类的外部实例化
3、私有的__clone阻止在类的外部clone对象
4、公有的静态方法用来获取对象的单例
实现封装MySQL单例的思路:
第一步:实现单例
第二步:初始化参数
第三步:连接数据库
第四步:操作数据
1、执行数据操作语句(增、删、改)
2、执行数据查询语句
a) 返回二维数组
b) 返回一维数组
c)返回一行一列
代码的实现:
<?php
class MySQLDB {
private static $instance;//私有的静态属性用来保存对象的单例
private $host;
private $port;
private $user;
private $pwd;
private $charset;
private $link;
private $dbname;
//私有的构造方法用来阻止在类的外部实例化
private function __construct($param){
$this->initData($param);
$this->connectDB();
}
//私有的__clone阻止在类的外部clone对象
private function __clone(){ }
//获取单例,公有的静态方法用来获取对象的单例
static function getInstance($param){
if(!self::$instance instanceof self){
self::$instance = new self($param);
}
return self::$instance;
}
//初始化参数
private function initData($param = array()){
$this->host = $param['host']??'127.0.0.1';
$this->port = $param['port']??'3306';
$this->user = $param['user']??'';
$this->pwd = $param['pwd']??'';
$this->dbname = $param['dbname']??'';
$this->charset = $param['charset']??'utf8';
}
//连接数据库
private function connectDB(){
$this->link =@mysqli_connect($this->host,$this->user,$this->pwd,$this->dbname);
if(!$this->link){
echo '连接数据库失败';
echo '错误:'.mysqli_connect_error,'<br>';
echo '错误码:'.mysqli_connect_errno,'<br>';
exit;
}
mysqli_set_charset($this->link,$this->charset);
}
//执行数据库的增、删、改、查语句
private function executeSQL($sql){
$rs = mysqli_query($this->link,$sql);
if(!$rs){
echo '执行sql语句失败';
echo '错误:'.mysqli_error($this->link);
echo '错误码:'.mysqli_errno($this->link);
exit;
}
return $rs;
}
//执行增、删、改 并返回执行结果(true 或 false)
function executeZSG($sql){
if(in_array(substr($sql,0,6),array('delete','update','insert'))){
return $this->executeSQL($sql);
}else{
echo '非法访问<br>';
exit;
}
}
//获取自动增长的编号
function getIncrement(){
return mysqli_insert_id($this->link);
}
//执行查询语句
private function query($sql){
if(substr($sql,0,4) == 'desc' || substr($sql,0,4) == 'show' || substr($sql,0,6) == 'select'){
return $this->executeSQL($sql);
}else{
echo '非法访问<br>';
exit;
}
}
// 执行查询语句,返回二维数组
function fetchAll($sql,$type='assoc'){
$rs = $this->query($sql);
$type = $this->getType($type);
return mysqli_fetch_all($rs,$type);
}
//匹配一维数组
function fetchRow($sql,$type='assoc'){
$list = $this->fetchAll($sql,$type);
if(!empty($list)){
return $list[0];
}
return array();
}
//匹配一行一列
function fetchColumn($sql){
$list = $this->fetchAll($sql,'num');
if(!empty($list)){
return $list[0];
}
return null;
}
//获取匹配类型
private function getType($type){
switch($type){
case 'num':
return MYSQLI_NUM;
case 'both':
return MYSQLI_BOTH;
default:
return MYSQLI_ASSOC;
}
} }
$param = array(
'user' => 'root',
'pwd' => 'root',
'dbname' => 'mycool'
);
//获取单例
$db=MySQLDB::getInstance($param);
// var_dump($db);
//更新
// $db->executeZSG("update b set age=122 where id=11");
//插入
// if($db->executeZSG("insert into b values (null,55,66,22)"))
// echo '编号是:'.$db->getIncrement();
// 删除
// if($db->executeZSG("delete from b where id=11"))
// echo '删除成功';
//查询
// $list=$db->fetchAll('select * from b','assoc');
// var_dump($list);
// $list=$db->fetchRow('select * from b where id=9','num');
// var_dump($list);
// $list=$db->fetchColumn('select count(*) from b','assoc');
// var_dump($list);
小结一下:
1、instanceof 用来判断对象是否属于某个类
2、参数必须从外部传递到内部,不能写死到类的内部。
3、为了保证代码的可重用性,一个方法只实现一个功能,所以初始化参数和连接数据库分到两个方法中。