Mysql(基础库)----mysqli(升级库)----pdo(操纵不同类型的数据库)
Pdo是什么?是接口,是抽象的抽象类。pdo是一套API,使用PHP语言,是模版->函数->实现->厂商
***.dll动态连接数据库文件,就是函数库。
为了解决什么?是为了解决PHP操纵数据库,采用的是面向对象,规范化的,共用的一套标准,适用所有数据库。减少代码重写
1.pdo
①简介
PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。实现 PDO 接口的每个数据库驱动可以公开具体数据库的特性作为标准扩展功能。 注意利用 PDO 扩展自身并不能实现任何数据库功能;必须使用一个 具体数据库的 PDO 驱动(就是函数) 来访问数据库服务。
PDO 提供了一个 数据访问 抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。 PDO 不提供 数据库 抽象层;它不会重写 SQL,也不会模拟缺失的特性。如果需要的话,应该使用一个成熟的抽象层。
从 PHP 5.1 开始附带了 PDO,在 PHP 5.0 中是作为一个 PECL 扩展使用。 PDO 需要PHP 5 核心的新 OO 特性,因此不能在较早版本的 PHP 上运行。
不需要安装,只需要在配置文件里释放插件。
Pdo是以面向对象的方式操作,具有面向对象访问常量的方法
②预定义常量
PDO::PARAM_BOOL ( integer )
表示布尔数据类型。
PDO::PARAM_NULL ( integer )
表示 SQL 中的 NULL 数据类型。
PDO::PARAM_INT ( integer )
表示 SQL 中的整型。
等等。。
③连接与连接管理
连接是通过创建 PDO 基类的实例而建立的。不管使用哪种驱动程序,都是用 PDO 类名。构造函数接收用于指定数据库源(所谓的 DSN)以及可能还包括用户名和密码(如果有的话)的参数。
Example #1 连接到 MySQL
<?php
$dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass );
?>
如果有任何连接错误,将抛出一个 PDOException 异常对象。如果想处理错误状态,可以捕获异常,或者选择留给通过 set_exception_handler() 设置的应用程序全局异常处理程序。
Example #2 处理连接错误
<?php
try {
$dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass );
foreach( $dbh -> query ( 'SELECT * from FOO' ) as $row ) {
print_r ( $row );
}
$dbh = null ;//关闭连接
//PDOException错误异常
} catch ( PDOException $e ) {
print "Error!: " . $e -> getMessage () . "<br/>" ;
die();
}
?>
连接数据成功后,返回一个 PDO 类的实例给脚本,此连接在 PDO 对象的生存周期中保持活动。要想关闭连接,需要销毁对象以确保所有剩余到它的引用都被删除,可以赋一个 NULL 值给对象变量。如果不明确地这么做,PHP 在脚本结束时会自动关闭连接。
Example #3 关闭一个连接
<?php
$dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass );
// 在此使用连接
// 现在运行完成,在此关闭连接
$dbh = null ;
?>
很多 web 应用程序通过使用到数据库服务的持久连接获得好处。持久连接在脚本结束后不会被关闭,且被缓存,当另一个使用相同凭证的脚本连接请求时被重用。持久连接缓存可以避免每次脚本需要与数据库回话时建立一个新连接的开销,从而让 web 应用程序更快。
Example #4 持久化连接
<?php
$dbh = new PDO ( 'mysql:host=localhost;dbname=test' , $user , $pass , array(
PDO :: ATTR_PERSISTENT => true
));
?>
Note:
如果想使用持久连接,必须在传递给 PDO 构造函数的驱动选项数组中设置 PDO::ATTR_PERSISTENT 。如果是在对象初始化之后用 PDO::setAttribute() 设置此属性,则驱动程序将不会使用持久连接。
Note:
如果使用 PDO ODBC 驱动且 ODBC 库支持 ODBC 连接池(有unixODBC 和 Windows 两种做法;可能会有更多),建议不要使用持久的 PDO 连接,而是把连接缓存留给 ODBC 连接池层处理。 ODBC 连接池在进程中与其他模块共享;如果要求 PDO 缓存连接,则此连接绝不会被返回到 ODBC 连接池,导致创建额外的连接来服务其他模块。
④至⑦了解
④事物与自动提交
⑤预处理语句与存储过程
⑥错误与错误处理
⑦大对象
一个完整的数据库操作
//设置连接数据库的参数值
//参数分别为数据库名,端口号,数据库名,字符集
$dbp='mysql:host=localhost;port=3306;dbname=pg37;charset=utf8';
$user='root';
$password='';
//创建连接数据库的pdo对象
$pdo=new PDO($dbp,$user,$password);
//var_dump($pdo);
//PDOException 错误异常
//编写sql语句,发送到数据库端执行并接收返回结果
$infos=$pdo->query('select * from student',PDO::FETCH_NUM);
//PDO::FETCH_NUM处理返回结果集,以索引数组返回
2.pdo类(重点)
PDO::FETCH_BOTH返回数组的下标类型
DML使用PDO->exec
DQL使用PDO->query,有值返回,pdo对象,无值返回false;
表单提交数据通过network
不在apache下面运行会报错
得到post数组变量
将浏览器上的内容是经过,编码urlencode得到的,要经过解码urldecode还原
Js页面跳转,location.href=’url’;
写在函数外面setInterval();
删除并不是真的删除,是将其隐藏
数据库的备份
php封装
使用.ini相关文件
读取parse_ini_file()
pdo封装使用lianxirenxitong.zip文件
Pdo封装使用预编译语句lianxirenxitong2.zip文件
- PDOStatement 类
PdoStatement->fetch() 从结果集中获取下一行
PdoStatement->fetchAll() 返回一个包含结果集中所有行的数组
PdoStatement->fetchObject()获取下一行并作为一个对象返回
加密md5加密一般像下面这样
md5(md5(md5($pwd).'lovo').'pg37');
手册中安全->数据库安全->
还有一个加密方式crypt()
配置文件
if(file_exists('db.ini')){
//file_exists('db.ini')引入配置文件
$arr = parse_ini_file('db.ini');//将配置文件里面的内容赋值给数组,返回一个索引数组
}else{
exit('没有找到对应的配置信息文件...');
}
pdoStatement->FetchAll()
pdoStatement->FetcchObject()
有问题
- PDOException 异常类
扩展异常处理
Pdo中的错误异常
异常:正常中发生的意外,异常类Exception,错误Error
什么情况下出现notice错误,什么情况出现warning,什么情况出现fatal error 当一个数组和一个字符串相加时。
Final private function __clone();限制错误异常被复制
Is_numeric()判断是否为数字
Iconv()转码
以前Exception
<?php
/**
* 异常处理代码
* User: fu
* Date: 2017/7/28
* Time: 14:22
*/
/*
* 显示错误信息提示:errors,warnings,notices
*/
echo $p; // Notice: Undefined variable
// Warning: include(Test.php): failed to open stream: No such file or directory
// Warning: include(): Failed opening 'Test.php' for inclusion (include_path='.;C:phppear')
include 'Test.php';
//Fatal error: Unsupported operand types
echo 'abc'+array('aaa');
//Fatal error: Class 'Person' not found
$person = new Person();
/*
* 异常的编号必须是数字值
*/
function daoShu($num){
if(!is_numeric($num)){
throw new Exception('不是正确的数字值','101');
} else if(!$num){
throw new Exception('数字不能为0','102');
}
return 1/$num;
}
/**
* 异常使用try块包含,但是如果执行中出现了异常代码,则后面的代码不会再执行了,而跳转到catch块执行
* finally块无论是否会发生异常,始终会在最后执行
*/
try{
// $n1 = daoShu('abc');
// $n1 = daoShu(0.0);
$n2 = daoShu('33.333');
echo $n2;
}catch (Exception $ex){
echo '异常序号:'.$ex->getCode().',异常描述:'.$ex->getMessage().'<br>';
} finally{
echo '异常处理模块结束<br>';
}
?>
PDOException
header('content-type:text/html;charset=utf-8');
try {
$dbh = new PDO('mysql:host=localhost;dbname=pg37;port=13306;charset=utf8',
'root', '');
foreach($dbh->query('SELECT * from student') as $row) {
print_r($row);
echo '<br>';
}
$dbh = null;
} catch (PDOException $e) {
print '错误编号:'.$e->getCode().",错误消息: " . iconv('gbk','utf-8',$e->getMessage()) . "<br/>";
die();
}
- PDO 驱动
三、安全
1.sql注入
在登录时,输入用户和密码,即时密码不对都能查询结果
乌云网站,报告这个网站出了什么问题
2.为了防止用户泄漏
使用pdo中的预编译语句
先使用pdo->prepare($sql);
在使用$pdoStatment->execute(array(传入要查询的值));
PDOStatement::execute — 执行一条预处理语句
直接传值用
1.提高数据库的效率:减少编译次数,减少连接次数。当出现当量操作sql语句,比如大量将数据插入数据库中,原来的那种单个执行sql语句或者批量执行sql语句的做法,显然是不可行的,因为无论是单个执行还是批量执行都会连续的发送sql语句向数据库中,数据库接到sql语句对它进行编译处理,从而导致效率底下。而php中出现的预编译解决了这个问题,他的工作原理是:将sql语句发过去,数据库对这一个sql语句进行预编译处理。之后你只需要将要数据发送到数据库即可。
2.下面就我在学习中的一个实例以作为说明:
<?php
这里是mysqli的例子,现在使用的是pdo
//预编译不仅可以提高效率,还可以防止SQL注入攻击
$mysqli=new mysqli("localhost", "root", "root", "test303");
if($mysqli->connect_error){
die("连接失败!".$mysqli->connect_error);
}
//1.穿件预编译对象
$sql="insert into account values(?,?);";//当传入值时自动会被替换
$mysqli_stmt=$mysqli->prepare($sql);//$mysqli->prepare准备执行SQL语句
//2.绑定参数
$id=4;
$account=400;
//3.将绑定的值赋值为?,类型要一直
$mysqli_stmt->bind_param("ii", $id, $account); //绑定变量来一份声明中作为参数
//4.执行
$res=$mysqli_stmt->execute();//执行准备好的查询
if (!$res){
die("操作失败".$mysqli_stmt->error);
}else {
echo "操作成功!";
}
//5.释放资源
$mysqli->close();
?>
3.数据表
create table acount(
id int primary key,
account int
);
Pdo例子
<?php
/* Execute a prepared statement by passing an array of values */
$sth = $dbh -> prepare ( 'SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?' );
$sth -> execute (array( 150 , 'red' ));
$red = $sth -> fetchAll ();
$sth -> execute (array( 175 , 'yellow' ));
$yellow = $sth -> fetchAll ();
?>
3.类型约束
简单提示
判断是否为数组is_array()
rowCount()