数据库抽象层--php高级最详细教程

来源:互联网 发布:无锡软件研究所有哪些 编辑:程序博客网 时间:2024/05/10 20:12

数据库抽象层PDO 原创



使用PDO的好处?


PDO(PHP Data Object) 的出现让PHP达到一个新的高度。PDO扩展类库为PHP访问数据库定义了一个轻量级的、一致性的接口,
它提供了一个数据访问抽象层,这个,无论你使用什么数据库,都可以通过一致的函数执行查询和获取数据。大大简化了数据库的
操作,并能够屏蔽不同数据库之间的差异。使用PDO可以很方便的进行跨数据库程序的开发,以及不同数据库间的移植,是将来
PHP在数据库处理方面的主要发展方向。


PDO所支持的数据库






PS:要确定所处环境中有可用的PDC驱动程序,可以在浏览器中通过加载phpinfo()函数
,查看PDO部分的列表,或者通过查pdo_drivers()函数返回的数组。


PDO的安装


PS:PDO随PHP5.1发行,在PHP5.0的PECL扩展中也可以使用,PDO需要PHP5核心面向对象特征
性的支持,所以它无法运行于之前的PHP版本中。


Linux环境下启动对MySQL的PDO驱动程序支持,需要在安装PHP5.1以上版本的源代码包环境时,
向configure命令中添加如下标志:
--with-pdo-mysql=/usr/local/mysql     //其中“/usr/local/mysql”为MySQL服务器安装目录


PS:如果在安装PHP环境时,要开启其他各个特定PDO驱动程序的更多信息,请参考执行configure 
--help命令所获得的帮助结果。


Windows环境下的配置:
在Windows环境下PHP5.1以上版本中,PDO和主要数据库的驱动同PHP一起作为扩展发布,要激活它们只需要简单的编辑php.ini文件。
extension=php_pdo.dll //所有PDO驱动程序共享的扩展,必须有
extension=php_pdo_mysql.dll //如果使用MySQL,那么就添加这一行
extension=php_pdo_mssql.dll //如果使用SQL Server,那么添加这一行
extension=php_pdo_odbc.ll  //如果使用ODBC驱动程序,那么添加这一行
extension=php_pdo_oci.ll  //如果使用Oracle驱动程序,那么添加这一行
保存修改的php.ini文件变化,重启Apache服务器,查看phpinfo()函数,


如下图:


创建PDO对象


PDO的构造方法:


创建PDO对象其实就是在new PDO($dsn,[,username[,password[,array driver_optionss]]]) 的括号中填写必要的参数来进行构造方法的初始化
PDO的构造方法原型如下:
__construct(string dsn [ , string username [ , string password [ , array driver_options]]])  //PDO的构造方法
构造方法参数说明:
第一个参数:
dsn  (data source  name) 数据源名 必选参数 用来定义一个确定的数据库和必须用到的驱动程序。 
dsn 格式  如下所示:
oci:dbname=//localhost:1521/mydb //连接到Oracle服务器的DSN, oci:作为驱动前缀, 主机 localhost, 端口 1521, 数据库 mydb
mysql:host=localhost;dbname=testdb //连接到MySQL服务器的DSN,mysql:作为驱动前缀,主机 localhost, 数据库 testdb
第二个参数和第三个参数:
构造方法中的第二个参数username和第三个参数password 分别用于指定连接数据库的用户名和密码,是可选参数。
第四个参数:
最后一个参数driver_option 需要一个数组,用来指定连接所需要的所有额外选项,传递附加的调优参数到PDO或底层驱动程序。


以多种方式调用构造方法:


1.将参数嵌入到构造函数


<?php
   try{
        $dsn = new PDO("uri:file///usr/local/dbconnect",'webuser','password')
}catch(PDOException $ex){
echo '连接数据库失败:'.$ex->getMessage();
        }


文件dbconnect的格式:
mysql:host=localhost;dbname=testdb;   


PS:testdb后的分号可以不加 ,host 和dbname的顺序不是固定的。


2.将参数存放在文件中


<?php
   try{
        $dsn = new PDO("mysql:dbname=testdb;host=localhost;",'webuser','password')
}catch(PDOException $ex){
echo '连接数据库失败:'.$ex->getMessage();
        }
  


3.引用php.ini文件


<?php
   try{
        $dsn = new PDO("oraclepdo",'webuser','password')
}catch(PDOException $ex){
echo '连接数据库失败:'.$ex->getMessage();
        }


在php.ini中为DSN指定的别名为oraclepdo:
[PDO]
pdo.dsn.oraclepdo="OCI:dbname=//localhost:1521/mydb;charset=UTF-8";


PDO与连接相关的选项






PS:在创建PDO对象时,有一些与数据库连接有关的选项,可以将必要的几个选项组成数组传递给构造方法的
第四个参数 driver_option中,用来传递附加的调优参数到PDO或底层驱动程序


传入写法如下:
new PDO("mysql:host=localhost;dbname=testdb;",'root','',array(3=>2,PDO::ATTR_PERSISTENT=>true))


PDO对象中的成员方法






PS:当PDO对象创建成功以后,与数据库的连接已经建立,就可以使用该对象了。PHP与数据库服务直接的交互都是
通过PDO对象中的成员方法实现的。


使用PDO对象


调整PDO的行为属性


PDO属性的设置可以查看PHP帮助文档(http://www.php.net/pdo).
如果在创建PDO对象时,没有在构造方法中最后一个参数设置过的属性选项,也可以在创建完对象以后,通过
PDO对象中的setAttribute()和getAttribute()方法设置和获取这些属性的值


getAttribute的使用:
该方法值需要提供一个参数,传递一个特定的属性名称,如果执行成功,则返回该属性所指定的值
以下实例简写:
//try{}catch(){} 这里省略了,不写了。 
$pdo = new PDO("mysql:host=localhost;dbname=test;",'root','');
$pdo->getAttribute(PDO::ATTR_ERRMODE); //当前PDO错误处理的方式


setAttribute的使用:
这个方法需要传入两个参数,第一个参数提供PDO对象特定的属性名,第二个参数则是这个指定的属性赋一个值。
以下实例简写:
//try{}catch(){} 这里省略了,不写了。 
$pdo = new PDO("mysql:host=localhost;dbname=test;",'root','');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //设置抛出异常处理错误


PDO处理PHP程序和数据库之间的数据类型转换


如果结果集中的某列包含一个NULL值,PDO则会将其映射为PHP的NULL值。Oracle在将数据
返回到PDO时会将空字符串转换为NULL,但是PHP支持的任何其他数据库都不会这样处理,从
而导致了可移植性问题。PDO提供了一个驱动程序级属性PDO_ATTR_ORACLE_NULLS,该属
性会为其他数据驱动程序模拟此行为。此属性设置为TRUE,在获取时会把空字符串转换为NULL,
默认情况下该属性值为FALSE.如下:
$pdo->setAttribute(PDO::ATTR_ORACLE_NULLS,true);
该属性设置以后,通过$pdo对象打开的任何语句中的空字符串都将被转换为NULL.


PDO的错误处理模式


PDO提供了三种不同的错误处理模式,不仅可以满足不同风格的编程,也可以调整扩展处理错误的方式


1.PDO::ERRMODE_SILENT
这是默认模式,在错误发生时不进行任何操作,PDO将只设置错误代码。开发人员可以通过对象中的errorCode和errorInfo()方法对语句和数据库对象进行检查。


2.PDO::ERRMODE_WARNING
发出一条PHP传统E_WARNING消息,可以使用常规的PHPCUOWU 错误处理程序捕获该警告
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
3.PDO::ERRMODE_EXCEPTION
PDO还将抛出一个PDOException,并设置其属性,以反映错误代码和错误消息。这种设置在调试中
很有用,因为它会放大脚本中产生错误的地方该错误方式配合try{}catch(){}使用最好。 
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);


使用PDO执行SQL语句


在PHP脚本中,通过PDO执行SQL查询与数据库进行交互,可以分为三种不同的策略,使用哪一种方法取决你做什么操作。


1.使用PDO::exec()方法
当执行INSERT、UPDATE、DELETE等没有结果集的查询时,使用PDO对象中的exec()方法去执行,该方法成功执行后,
将会返回受影响行数。
示例代码如下:
$query = "UPDATE user set phone='15607925362' WHERE id='35'";
$affected = $dbh->exec($query); //执行语句返回受影响行数$affected。 
//受影响函数同样适用于DELETE 删除语句,但是插入语句insert不好用了。要使用lastInsertId()来获取最后插入id


//插入语句INSERT
$query = "INSERT INTO user(name,phone,email) values('vilin','15607925361','23506583@qq.com')";
$dbh->exec($query);
$dbh->lastInsertID(); //获取最后的插入id




2.使用PDO::query()方法
当执行返回结果集的SELECT查询时,或者所影响的行数无关紧要时,应当使用PDO对象中的query()方法,如果该方法成功执行指定的查询,
则返回一个PDOStatement对象。如果使用了query()方法,并想了解获取数据的总行数,可以使用PDOStatement对象中的rowCount()方法
获取,示例代码如下:
<?php
$dbh = new PDO("mysql:host=localhost;dbname=test;",'root',''); //建议写到try{}catch(){}中 
$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //设置对象错误处理模式
$query = "SELECT name,phone,email FROM user WHERE id='34'";  //准备sql查询语句
        try{
$stmt = $dbh->query($query);  //执行语句
echo "一共从表中获取到".$stmt->rowCount()."条记录:\n";
foreach($stmt as $row){  //遍历$dbh->query($query);来得到数据
echo $row['name']."\t";
echo $row['phone']."\t";
echo $row['email']."\n";
}
}catch(PDOException $ex){
echo $ex->getMessage();
}





3.使用PDO::quote()方法
可以使用PDO::quote()过滤一些特殊字符,防止一些能引起SQL注入的代码。我们在PDO中使用quote()方法实现,
实例如下:
$query = "SELECT * FROM users WHERE login=".$dbh->quote($_POST['login'])." AND passwd=".$dbh->quote($_POST['pass']);


//安全转义 例如下面这个奇葩的英文名字
$name = "Job's HHH";
//使用此方法转义
$name = $pdo->quote($name);
//通过quote方法转义之后的字符串,会将特殊字符转义,并将两端加上单引号
echo $name.'<br>'; //   'Job\'s HHH'
//我们使用的时候直接使用转义后的变量就可以了,不需要再加上单引号,否则报错
$sql = "insert into shop_user(username,age,money) values($name,19,39000)";

$rows = $pdo->exec($sql);


4.使用PDO::prepare()和PDOStatement::execute()两个方法
当同一个查询需要多次执行时(有时需要迭代传入不同的列值),使用预处理语句的方式来实现效率会很更高。从MySQL4.1开始,
就可以结合MySQL使用PDO对预处理语句的支持。使用预处理语句就需要使用PDO对象中的prepare()方法去准备一个将要执行
的查询,在使用PDOStatement对象中的execute()方法来执行


PDO对预处理语句的支持


使用预处理语句的好处?


1.提高命令的处理效率。
2.可以有效防止SQL注入。


PDOStatement对象的使用


通过执行PDO对象中query()方法返回的PDDOStatement类对象,只代表一个结果集对象。
而通过执行PDO对象中prepare()方法返回的PDOStatement类对象则为一个查询对象,能定义和执行参数化的SQL命令.
PDOStatement类中的全部成员方法如下


实例:
<?php
header('content-type:text/html;charset=utf-8');

// PDO的使用


    //准备一个数据源  DSN
    $dsn = "mysql:host=localhost;dbname=test";


    //实例化PDO对象
    try{
        $pdo = new PDO($dsn,'root','',array('3'=>'1'));
    }catch(PDOException $ex){
        echo '数据库连接失败';
    }


    //设置字符集
    $sql = "set names utf8";
    $pdo->exec($sql);


    //预处理
    //会自动使用安全转义   一个值  例如Like后面,占位符要代表一个完整的值
    $sql = "select * from user where name like  ?";
    $stmt = $pdo->prepare($sql);


    //绑定参数
    $stmt->bindParam(1,$key);


    //赋值
    $key = "%pan%"; //会安全过滤


    //执行
    $bool = $stmt->execute();   

//设置 setFetchMode()fetch()或fetchAll()取值方式 
//PDO::FETCH_ASSOC关联数组  PDO::FETCH_NUM 索引数组 PDO::FETCH_OBJ 对象  PDO::FETCH_BOTH 索引和关联
$stmt->setFetchMode(PDO::FETCH_ASSOC);
//第一种取值方法

/* foreach($stmt as $val){
list($id,$name,$age,$money) = $val;
echo "$id--$name--$age--$money<br>";
} */

//第二种取值方法
//fetch() 
/* while($row = $stmt->fetch()){ 
echo'<pre>';
print_r($row);
echo '</pre>'; 
$val= array_values($row);
$key = array_keys($row);
list($id,$name,$age,$money) = $val;
echo "--$id--$name--$age---$money----<br>";

}*/

//第三种取值方法
//fetchAll()
/* $rows = $stmt->fetchAll(); 
echo '<pre>';
print_r($rows);
echo '</pre>';
 
foreach($rows as $row){
$key = array_keys($row);
   $val = array_values($row);
list($id,$name,$age,$money) = $val;
echo "$id--$name--$age--$money<br>";
} */

//第四种方法 取值每次取一行   然后再取一列的某个值  执行一次 指针向下移动一条

/* $one = $stmt->fetchColumn(1);
echo $one.'<br>';
$two = $stmt->fetchColumn(1);
echo $two.'<br>';
$three = $stmt->fetchColumn(1);
echo $three.'<br>'; */

/* while($num = $stmt->fetchColumn(1)){
echo "$num<br>";
} */

//第五种类似于LIST的取值

$stmt->bindColumn(1,$name);
$stmt->bindColumn(2,$age);

$stmt->fetch();
echo $name.'<br>';
echo $age.'<br>';



















/* $arr=array(
'ret'=>'0',
'msg'=>'ok',
'url'=>''


);
print_r($arr);
$str= json_encode($arr);
echo $str;
print_r(json_decode($str,true)); */






占位符实例:(:)
<?php
header('content-type:text/html;charset=utf-8');

//PDO的使用
//准备dsn data source name
$dsn = "mysql:host=localhost;dbname=test";

//实例化PDO对象
try{
$pdo = new PDO($dsn,'root','');
}catch(PDOException $ex){
echo $ex->getMessage();
}

//设置字符集
$sql = "set names utf8";
$pdo->exec($sql);

//预处理
//问号占位符号 ?
//冒号占位符号 :
//准备模板 此处冒号不加引号,冒号不能省略
$sql = "insert into user(name,age,money) values(:name,:age,:money)";
$stmt = $pdo->prepare($sql);

//绑定参数 此处冒号可省略,但是一定要加引号
$stmt->bindParam('name',$name);
$stmt->bindParam('age',$age);
$stmt->bindParam('money',$money);

//赋值
$name = 'liangliang';
$age = 23;
$money = 43000;

$stmt->execute();


//赋值
$name = "tietie";
$age = 25;
$money = 45000;


$stmt->execute();


不绑定参数,简写模式
<?php
header('content-type:text/html;charset=utf-8');

//PDO的使用
//准备dsn data source name
$dsn = "mysql:host=localhost;dbname=test";

//实例化PDO对象  PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
$arr = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
try{
$pdo = new PDO($dsn,'root','',$arr);
}catch(PDOException $ex){
echo $ex->getMessage();
}

/*
//插入语句操作
//预处理
//占位符号及批量绑定
$sql = "insert into user(name,age,money) values(:name,:age,:money)";
$stmt = $pdo->prepare($sql);

//批量执行
$stmt->execute(array('name'=>'jiajia','age'=>21,'money'=>40000)); 
*/

/* //删除语句操作
//预处理
//占位符号 及批量绑定
$sql = "delete from user where id=:id";
$stmt = $pdo->prepare($sql);

//批量执行 简化写法 省去绑定参数 和赋值
$stmt->execute(array('id'=>3)); */

//更新语句操作
//预处理
//占位符号及批量绑定
$sql = "update user set name='huahua' where id=:id";
$stmt = $pdo->prepare($sql);

//批量执行 简化写法 省去参数绑定和赋值
$stmt->execute(array('id'=>4));


问号占位符:
<?php
header('content-type:text/html;charset=utf-8');

//PDO的使用
//准备dsn data source name
$dsn = "mysql:host=localhost;dbname=test";

//实例化PDO对象
try{
$pdo = new PDO($dsn,'root','');
}catch(PDOException $ex){
echo $ex->getMessage();
}

//设置字符集
$sql = "set names utf8";
$pdo->exec($sql);

//预处理
//问号占位符号 ?
//冒号占位符号 :
//准备模板
$sql = "insert into user(name,age,money) values(?,?,?)";
$stmt = $pdo->prepare($sql);

//绑定参数  1  2  3按问号顺序进行绑定
$stmt->bindParam(1,$name);
$stmt->bindParam(2,$age);
$stmt->bindParam(3,$money);

//赋值
$name = 'liangliang';
$age = 23;
$money = 43000;

$stmt->execute();


//赋值
$name = "tietie";
$age = 25;
$money = 45000;


$stmt->execute();


PDO的事务处理


事务处理概述


事务是确保数据库一致的机制,是一个或一系列的查询,作为一个单元的一组有序的数据库操作。如果组中的所有SQL语句都操作成功,则认为事务成功,事务则被提交,其修改将作用于所有其他数据库进程。即使在事务的组中只有一个环节操作失败,事务也不成功,则整个事务将被回滚,该事务中所有操作都将被取消。事务功能是企业级数据库的一个重要部分,因为很多业务过程都包括多个步骤。事务处理有4个重要特征:原子性(Atomicity)、一致性(Consistency)、独立性(Isolation)和持久性(Durability)即ACID


实例一


<?php
header('content-type:text/html;charset=utf-8');


//pdo的使用
//准备dsn data source name
$dsn = "mysql:host=localhost;dbname=test";


//实例化一个PDO对象
try{
$pdo = new PDO($dsn,'root','',array(3=>2));
}catch(PDOException $ex){
echo $ex->getMessage();
}


//使用数据设置字符集
$sql = "set names utf8";
$pdo->exec($sql);


//常规操作


//mysql>set autocommit = 0  关闭自动提交后 需要使用commit 确认 使用rollback 回滚
//mysql>set autocommit = 1  开启自动提交 默认是开启的 语句回车后 会直接执行 无法 回滚
//事务操作 表引擎必须是InnoDB
//启动事务 $pdo->beginTransaction();(pdo操作语句)    mysql>begin;(操作数据的的语句) 自动提交关闭 
$pdo->beginTransaction();
//中间可以做一系列的操作 任何一个环节失败,则整体失败
$money = 1;
$sql = "update shop_user set money = money - $money where id=1";
$rows = $pdo->exec($sql);


$sql = "update shop_user set money = money + $money where id=2";
$rows += $pdo->exec($sql);
if($rows == 2){
$pdo->commit(); //数据库操作语句 mysql>commit;
echo '转账成功';
}else{
$pdo->rollBack(); //数据库操作语句 mysql>rollback;
echo '转账失败';
}


try{
$pdo->beginTransaction();
//中间可以做一系列的操作 任何一个环节失败,则整体失败
$money = 1;
$sql = "update shop_user set money = money - $money where id=1";
$rows = $pdo->exec($sql);


$sql = "update shop_user set money = money + $money where id=2";
$rows = $pdo->exec($sql);


$pdo->commit(); //数据库操作语句 mysql>commit;
echo '转账成功';
}catch(PDOException $ex){
$pdo->rollBack(); //数据库操作语句 mysql>rollback;
echo '转账失败';


}



0 0
原创粉丝点击