目录
0x00 PHP操作数据库的3种方式
1.PHP的MySQL扩展
存在很多安全问题,php5.5.0已经废弃,并在将来可能被移除
2.php的mysqli扩展
php的MySQL扩展的增强版
3.php数据对象(PDO:PHP DATA OBJECT)
PDO提供了一个统一的接口,可以让你不用管具体要连接的数据库类型,可以无缝切换数据库服务器
要使用PDO,要保证PDO的扩展已经打开了
0x01 PDO连接数据库
PDO类
PDOStatement类
PDOException 异常类
<?php
try{
$db = new PDO($dsn,$username,$pwd);
}catch(PDOException $e){
echo 'fail to connection:'.$e->getMessage();
}
?>
1 <?php
9 try{
10 $db = new PDO('mysql:host=localhost;dbname=gaokao;port=3306;charset = utf8','root','root');
11 echo '连接成功';
12 //var_dump($db);
13 }catch(PDOException $e){
14 die('操作失败'.$e->getMessage());
15 }
17 ?>
0x02 PDO的exec的使用
<?php
11 try{
12 $db = new PDO('mysql:host=localhost;dbname=gaokao;p ort=3306;charset = utf8','root','root');
13 echo '连接成功';
14 var_dump($db);
15 }catch(PDOException $e){
16 die('操作失败'.$e->getMessage());
17 }
18 $name = "梁朝伟";
19 $pwd = md5('123');
20 $sql = "INSERT INTO user (name,pwd)VALUES('$name','$pwd');";
21 $ret = $db->exec($sql);
?>
其中$ret是语句影响的行数,不会返回select查询的结果;
那么查询数据库应该用什么呢?用prepare();
0x03 关于PDOStatment
1.prepare() 预处理
返回一个PDOStatement类的对象。
主要用来提高相同SQL模块查询性能,并且能防止SQL注入(推荐用这个)
使用方式1:
PDOStatement::bindParam(变量名,值) 绑定一个参数到指定的?占位符处。
PDOStatement::execute() 执行一条预处理语句。 返回值为是否执行成功。
<?php
$stmt = $db->prepare('INSERT INTO user(name,pwd) VALUES(?,?)');
$name = '刘玉玲';
$pwd = md5('123');
$stmt->bindParam(1,$name);
$stmt->bindParam(2,$pwd);
$ret = $stmt->execute();
?>
使用方式2:
<?php
$stmt = $db->prepare('INSERT INTO user(name,pwd) VALUES(:u,:p)');
$name = '刘玉玲';
$pwd = md5('123');
$stmt->bindParam(:u,$name);
$stmt->bindParam(:p,$pwd);
$ret = $stmt->execute();
?>
使用方式3:推荐
<?php
$stmt = $db->prepare('INSERT INTO user(name,pwd) VALUES(:u,:p)');
$name = '刘玉玲';
$pwd = md5('123');
$data = [':u'=>$name,':p'=>$pwd];
$ret = $stmt->execute($data);
echo $db->lastInsertId();
?>
PDO::lastInsertId() 当sql语句执行插入操作后,通过该函数可以获得插入的Id
查询数据
通过PDOStatement::fetchAll()可以返回所有查询结果。默认既返回关联数组又返回索引数组
PDOStatement::fetchAll(PDO::FETCH_ASSOC) 只返回关联数组
PDOStatement::fetchAll(PDO::FETCH_NUM) 只返回索引数组
PDOStatement::fetch()只返回查询结果的中一条。默认返回关联数组和索引数组
PDOStatement::rowCount() 返回查询结果的行数
PDOStatement::errorInfo() 返回SQL语句的错误信息,是一个数组
PDOStatement::errorCode 返回错误码
$sql="SELECT * FROM user";
$stmt = $db->prepare($sql);
$ret = $stmt->execute();
echo '<pre/>';
var_dump($stmt->fetchAll());
echo '<pre/>';
echo stmt->rowCount();
print_r(stmt->errorInfo());
echo stmt->errorCode();
0x04 关于PDO类中事务的使用
事务是指单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行
例如:进行转账操作就必须用事务来完成。A给B转账,要么执行成功,A的账户余额减少(执行减少的SQL语句成功)并且B的账户余额增加(执行增加的SQL语句也成功)。
要么执行失败,A的账户余额不减少,B的账户余额也不增加。
必须是InnoDB的数据库引擎
流程:
<?php
try{
$db = new PDO('mysql:host=localhost;dbname=gaokao;charset=utf8','root','root');
}catch(PDOException $e){
die('连接失败:'.$e->getMessage());
}
//1.开启异常
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
try{
//2.开启事务
$db->beginTransaction();
$from = $db->exec('UPDATE user SET fee = fee-500 WHERE id =1');
$to = $db->exec('UPDATE user SET fee = fee+500 WHERE id = 2');
//3.如果上面两句都没有问题,就不会抛出异常,那么就提交。即让两句都真正生效
$db->commit()
}catch(PDOException $e){
//3.如果其中一句执行的有问题,那么就回滚。即让已经生效的生效的语句不要生效
$db->rollback();
echo $e->getMessage();
}
?>
0x05 其他的两种连接操作
mysql的扩展连接操作;
5.6之后已经废弃
<?php
//1.连接数据库
$conn = mysql_connect($host,$username,$pwd) or die('连接失败');
//2.选择某个数据库
mysql_select_db($dbname,$conn);
//3.执行sql语句
$result = mysql_query("select * from xxx表");
//4.提取数据
$row = mysql_fetch_row($result);
var_dump($row);
?>
mysqli的扩展连接,对象的形式
<?php
$db = new mysqli($host,$username,$pwd);
$result = $db->query('SELECT * FROM user');
$row = $result->fetch_row();
var_dump($row);
?>
0x06 单例模式
所谓单例模式,就是某个类在实例化的过程中只有一个实例,在数据库连接中使用单例模式实例化数据库连接对象,可以避免重复的实例化对象而造成的资源浪费。
实现单例模式的三个条件:
1.需要一个保存类的唯一实例的静态成员变量 属性为私有
2.构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义。并且防止外部克隆
3.必须提供一个访问这个实例的public 静态方法(通常为getInstance方法),从而返回唯一实例的一个引用。
为什么要静态成员变量和静态成员函数,因为他们不需要实例化就可以访问。
三私一公
<?php
class Db{
//存储类的唯一的实例化对象
private static $instance;
//禁止外部new类
private function __construct(){}
//禁止外部克隆对象。
private function __clone(){}
//对外访问的方法 实现类的实例
public static function getInstance(){
//判断是否有实例化,如果没有实例化,就实例化
if(!self::$instance instanceof Db){
self::$instance = new self();//相当于new Db()
}
//已经实例化,直接返回实例化
return self::$instance;
}
}
$db1 = Db:getInstance();
$db2 = Db:getInstance();
$db3 = Db:getInstance();
?>