PHP17 PDO
学习要点
- PDO简要
- PDO对象
- PDO对象的使用
- PDOStatement对象
- PDO事务处理
PDO简要
PHP支持那些数据库操作
MySQL,Oracle,SQLServer,SQLite、PostgreSQL等等
PHP如何操作数据库
- 通过函数:每种数据库开发一种函数,开发人员需要学习各种数据库操作函数。
- 通过数据库抽象层:抽象层理解为一系列访问数据库通用基类,包含了访问数据库的通用抽象方法。不同数据库采用抽象层加上驱动的方式访问。驱动相当于实现了抽象层数据访问方法的子类。
确认PHP支持PDO
- PHP.INI
extension=php_pdo_mysql.dll
extension=php_pdo_sqlite.dll
- PHPINFO()
- pdo_drivers()确认支持的驱动
print_r(pdo_drivers());
输出:
Array
(
[0] => mysql
[1] => sqlite
)
PDO抽象层预定义类
- PDO:数据库连接。
- PDOStatement:预处理语句执行后结果集(associated result set)。
- PDOException:PDO异常。
PDO对象
PDO对象的构造方法
PDO::__construct($dsn, [optional] $username, [optional] $passwd, [optional] $options)
Creates a PDO instance representing a connection to a database.
Parameters:
$dsn : datasource name.
[optional] $username
[optional] $passwd
[optional] $options : Param Array. Optimize PDO.
PDO构造方法的调用
1、将参数嵌入到构造方法
$dsn = 'mysql:dbname=myschool;host=localhost';
$user = 'root';
$password = 'rootkit';
try {
$pdo = new PDO ( $dsn, $user, $password );
} catch ( PDOException $ex ) {
echo '连接数据库失败:' . $ex->getMessage ();
}
if($pdo!=null){
echo '连接数据库成功!';
}else{
echo '连接数据库失败!';
}
端口非3306的dsn书写方式:
$dsn='mysql:host=localhost;port=9906;dbname=mydatabase',$user,$pwd,$opt);
2、参数放在文件中
- 配置文件:
- 程序代码:
3、引用php.ini文件
- php.ini配置文件中添加
- 重启服务器后,PHP代码访问方式
4、$options参数
PDO构造函数第四个参数,为PDO预定义常量关联数组,一般用来优化数据库操作,用来传递给PDO对象或者底层驱动。
PDO预定义常量,详见本文末附表。
例如:PDO持久化连接代码:
PDO持久化连接解释:该连接在使用完毕或者PHP脚本结束后并不会被关闭,而是被PHP缓存起来。当另一个使用相同凭证(主机、端口、数据库名、用户名、密码等信息完全一致)的PHP脚本请求建立连接时,PHP将直接返回之前被缓存起来的连接,从而达到连接重用。持久连接缓存可以避免每次访问数据库都要建立一个新连接的开销,从而让web应用程序更快。
PDO成员方法
方法名 |
描述 |
exec( ) |
执行一条SQL语句并返回影响的行数 |
query( ) |
执行一条SQL语句并返回一个结果集 |
prepare( ) |
为执行准备一条SQL语句,返回语句执行后的联合结果集(PDOStatement) |
beginTransaction( ) |
开始事务 |
rollBack( ) |
回滚一个事务 |
commit ( ) |
提交事务 |
quote ( ) |
返回添加了引号的字符串,以使其可用于SQL语句中 |
errorCode ( ) |
从数据库返回一个错误代号,如果有的话 |
errorInfo ( ) |
从数据库返回一个含有错误信息的数组,如果有的话 |
getAttribute( ) |
返回一个数据库连接属性 |
setAttribute ( ) |
设置一个数据库连接属性 |
lastInsertId( ) |
返回最新插入到数据库的行(的ID) |
PDO提供的成员方法可以完成与数据库之间的连接管理、存取属性、错误处理、查询执行、预处理语句、以及事务的操作。
PDO对象的使用
调整PDO的行为属性
1、调整方式
- 通过PDO构造方法第四个参数调整属性;
- 通过PDO的setAttribute()方法设置属性;通过getAttribute()获得属性值。
2、getAttribute()
$opt=array(PDO::ATTR_PERSISTENT => TRUE);
try {
$dbh = new PDO('mysql:dbname=myschool;host=localhost', 'root', 'rootkit', $opt);
} catch (PDOException $e) {
echo '数据库连接失败:'.$e->getMessage();
exit;
}
echo "<br>PDO是否关闭自动提交功能:"
.$dbh->getAttribute(PDO::ATTR_AUTOCOMMIT);
echo "<br>当前PDO的错误处理的模式:"
.$dbh->getAttribute(PDO::ATTR_ERRMODE);
echo "<br>表字段字符的大小写转换: "
.$dbh->getAttribute(PDO::ATTR_CASE);
echo "<br>与连接状态相关特有信息: "
.$dbh->getAttribute(PDO::ATTR_CONNECTION_STATUS);
echo "<br>空字符串转换为SQL的null:"
.$dbh->getAttribute(PDO::ATTR_ORACLE_NULLS);
echo "<br>应用程序提前获取数据大小:"
.$dbh->getAttribute(PDO::ATTR_PERSISTENT);
echo "<br>与数据库特有的服务器信息:"
.$dbh->getAttribute(PDO::ATTR_SERVER_INFO);
echo "<br>数据库服务器版本号信息:"
.$dbh->getAttribute(PDO::ATTR_SERVER_VERSION);
echo "<br>数据库客户端版本号信息:"
.$dbh->getAttribute(PDO::ATTR_CLIENT_VERSION);
3、setAttribute()
- 语法格式
public bool PDO::setAttribute ( int $attribute , mixed $value )
- 常用设置
Sets an attribute on the database handle. Some of the available generic attributes are listed below; some drivers may make use of additional driver specific attributes.
PDO::ATTR_CASE: Force column names to a specific case.
- PDO::CASE_LOWER: Force column names to lower case.
- PDO::CASE_NATURAL: Leave column names as returned by the database driver.
- PDO::CASE_UPPER: Force column names to upper case.
PDO::ATTR_ERRMODE: Error reporting.
- PDO::ERRMODE_SILENT: Just set error codes.
- PDO::ERRMODE_WARNING: Raise E_WARNING.
- PDO::ERRMODE_EXCEPTION: Throw exceptions.
PDO::ATTR_ORACLE_NULLS (available with all drivers, not just Oracle): Conversion of NULL and empty strings.
- PDO::NULL_NATURAL: No conversion.
- PDO::NULL_EMPTY_STRING: Empty string is converted to NULL.
- PDO::NULL_TO_STRING: NULL is converted to an empty string.
PDO::ATTR_STRINGIFY_FETCHES: Convert numeric values to strings when fetching. Requires bool.
PDO::ATTR_STATEMENT_CLASS: Set user-supplied statement class derived from PDOStatement. Cannot be used with persistent PDO instances. Requires array(string classname, array(mixed constructor_args)).
PDO::ATTR_TIMEOUT: Specifies the timeout duration in seconds. Not all drivers support this option, and its meaning may differ from driver to driver. For example, sqlite will wait for up to this time value before giving up on obtaining an writable lock, but other drivers may interpret this as a connect or a read timeout interval. Requires int.
PDO::ATTR_AUTOCOMMIT (available in OCI, Firebird and MySQL): Whether to autocommit every single statement.
PDO::ATTR_EMULATE_PREPARES Enables or disables emulation of prepared statements. Some drivers do not support native prepared statements or have limited support for them. Use this setting to force PDO to either always emulate prepared statements (if TRUE), or to try to use native prepared statements (if FALSE). It will always fall back to emulating the prepared statement if the driver cannot successfully prepare the current query. Requires bool.
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY (available in MySQL): Use buffered queries.
PDO::ATTR_DEFAULT_FETCH_MODE: Set default fetch mode. Description of modes is available in PDOStatement::fetch() documentation.
PDO处理PHP程序和数据库之间的数据类型转换
PDO::ATTR_ORACLE_NULLS (available with all drivers, not just Oracle): Conversion of NULL and empty strings.
- PDO::NULL_NATURAL: No conversion.
- PDO::NULL_EMPTY_STRING: Empty string is converted to NULL.
- PDO::NULL_TO_STRING: NULL is converted to an empty string.
只有Oracle数据库返回空字符串,PDO会将其转换为NULL。其他数据库可能原样返回。其他数据库为了模拟Oracle的效果,可以设置:
$pdo->setAttribute(PDO::ATTR_ORACLE_NULLS, true);
PDO的错误处理模式
PDO::ATTR_ERRMODE: Error reporting.
- PDO::ERRMODE_SILENT: Just set error codes.
- PDO::ERRMODE_WARNING: Raise E_WARNING.
- PDO::ERRMODE_EXCEPTION: Throw exceptions.
- PDO::ERRMODE_SILENT
默认方式,语句对象或者调用数据库对象出错可以通过PDO的errorCode()和errorInfo()方法对语句对象和数据库操作对象进行检查。
- PDO::ERRMODE_WARNING
PHP可以捕获告警信息。
设置方式:
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
- PDO::ERRMODE_EXCEPTION
PHP捕获PDO异常对象。PDO异常对象包含了错误代码和错误信息属性。
设置方式:
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
SQL错误代码和错误信息的定义:SQLSTATE
文件地址:wamp\bin\mysql\mysql5.6.17\include\ sql_state.h
使用PDO执行SQL语句
- 使用PDO::exec()
/*
* 数据库连接优化选项:
* 1、持久化连接:持久化
* 2、错误处理模式:抛出异常
* 3、空字符串转null值:打开
*/
$option = array (
PDO::ATTR_PERSISTENT => TRUE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS=>true
); try {
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
//增删改
$query="INSERT INTO users VALUES('tom','123','访客')";
$pdo->exec($query);
} catch ( PDOException $e ) {
echo '数据库操作失败:' . $e->getMessage ();
exit ();
}
- 使用PDO::query()
/*
* 数据库连接优化选项:
* 1、持久化连接:持久化
* 2、错误处理模式:抛出异常
* 3、空字符串转null值:打开
*/
$option = array (
PDO::ATTR_PERSISTENT => TRUE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS=>true
); try {
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
//增删改
//$query="INSERT INTO users VALUES('tom','123','访客')";
//$pdo->exec($query);
//查询
$query="SELECT * FROM users";
$pdostmt=$pdo->query($query);
echo "一共{$pdostmt->rowCount()}条记录<br>";
echo "id,account,pwd,role<br>";
foreach ($pdostmt as $row){
echo "{$row['id']},{$row['username']},{$row['userpassword']},{$row['userrole']}<br>";
}
} catch ( PDOException $e ) {
echo '数据库操作失败:' . $e->getMessage ();
exit ();
}
- 使用PDO::prepare()和PDOStatement::execute()
如果查询语句格式相同,每次需要传入的参数不同,可以考虑使用预处理方式。预处理分成两个步骤执行:
1、PDO对象的prepare()构建查询语句;
2、使用PDOStatement对象的execute()方法执行查询语句。
PDOStatement
PDOStatement对象方法
方法名 |
描述 |
bindColumn ( ) |
绑定一个PHP变量到结果集中的输出列 |
bindParam ( ) |
绑定一个PHP变量到一个预处理语句中的参数 |
bindValue ( ) |
绑定一个值到与处理语句中的参数 |
closeCursor( ) |
关闭游标,使语句可以再次执行 |
columnCount ( ) |
返回结果集中的列的数量 |
errorCode( ) |
从语句中返回一个错误代号,如果有的话 |
errorInfo( ) |
从语句中返回一个包含错误信息的数组,如果有的话 |
execute ( ) |
执行一条预处理语句 |
fetch( ) |
从结果集中取出一行 |
fetchAll( ) |
从结构集中取出一个包含了所有行的数组 |
fetchColumn ( ) |
返回结果集中某一列中的数据 |
getAttribute( ) |
返回一个 PDOStatement 属性 |
getColumnMeta( ) |
返回结果集中某一列的结构(metadata?) |
nextRowset( ) |
返回下一结果集 |
rowCount( ) |
返回SQL语句执行后影响的行数 |
setAttribute( ) |
设置一个PDOStatement属性 |
setFetchMode( ) |
为 PDOStatement 设定获取数据的方式 |
PDOStatement预处理语句实现步骤
1、创建PDO对象
2、准备SQL语句
- 使用命名参数作为占位符构建SQL语句:
$sql="INSERT INTO users VALUES(:username,:userpassword,:userrole)";
- 使用?作为占位符构建SQL语句:
$sql="INSERT INTO users VALUES(?,?,?)";
3、返回PDOStatement对象
$stmt=$pdo->prepare($sql);
4、绑定参数
$stmt->bindParam ( 'username', $name ); //命名参数绑定 $stmt->bindParam(1, $name); //?占位符绑定 $name = 'soon'; //变量值
5、执行查询
- 无参数的execute方法:$stmt->execute();
- 数组作为参数的execute方法:
$stmt->execute (array(":username"=>"andy",":userpassword"=>"andy123",":userrole"=>"访客"));
或者(省略命名参数前的“: ”)
$stmt->execute (array("username"=>"andy1","userpassword"=>"andy123","userrole"=>"访客"));
1-5步骤完整参考代码:
$option = array (
PDO::ATTR_PERSISTENT => TRUE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => true
); try {
// 1.创建PDO对象
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
// 2.准备SQL语句
$sql = "INSERT INTO users(username,userpassword,userrole) VALUES(:username,:userpassword,:userrole)";
// $sql="INSERT INTO users(username,userpassword,userrole) VALUES(?,?,?,?)";
// 3.返回PDOStatement对象
$stmt = $pdo->prepare ( $sql );
// 4.绑定参数(使用命名参数作为占位符)
// $stmt->bindParam ( 'username', $name );
// $stmt->bindParam ( 'userpassword', $pwd );
// $stmt->bindParam ( 'userrole', $role );
// 5.执行查询
$stmt->execute ( array (
"username" => "andy2",
"userpassword" => "andy123",
"userrole" => "访客"
) );
echo '受影响行数:'.$stmt->rowCount();
echo '<br>新增访客编号为:'.$pdo->lastInsertId(); } catch ( PDOException $e ) {
echo '数据库操作失败:' . $e->getMessage ();
exit ();
}
6、获取数据
- PDO的query()方法。
- PDOStatement的prepare()和execute()方法。
以上两种方式执行SELECT查询都是得到相同的结果集对象PDOStatement。
6.1、fetch()方法获取数据
PDO::FETCH_NUM: returns an array indexed by column number as returned in your result set, starting at column 0.
PDO::FETCH_ASSOC: returns an array indexed by column name as returned in your result set.
PDO::FETCH_BOTH (default): returns an array indexed by both column name and 0-indexed column number as returned in your result set.
PDO::FETCH_BOUND: returns TRUE and assigns the values of the columns in your result set to the PHP variables to which they were bound with the PDOStatement::bindColumn() method.
PDO::FETCH_LAZY: combines PDO::FETCH_BOTH and PDO::FETCH_OBJ, creating the object variable names as they are accessed.
PDO::FETCH_OBJ: returns an anonymous object with property names that correspond to the column names returned in your result set
示例代码:
$option = array (
PDO::ATTR_PERSISTENT => TRUE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => true
); try {
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
// 查询
$sql = "SELECT * FROM users";
// $stmt=$pdo->query($sql);
$stmt = $pdo->prepare ( $sql );
$stmt->execute (); echo "一共{$stmt->rowCount()}条记录<br>";
echo "id---account---pwd---role<br>";
// foreach ( $stmt as $row ) {
// echo "{$row['id']},{$row['username']},{$row['userpassword']},{$row['userrole']}<br>";
// } // while ($arr=$stmt->fetch(PDO::FETCH_NUM)){
// echo $arr[0].'---';
// echo $arr[1].'---';
// echo $arr[2].'---';
// echo $arr[3].'<br>';
// } // while ( $arr = $stmt->fetch ( PDO::FETCH_ASSOC ) ) {
// echo $arr ['id'] . '---';
// echo $arr ['username'] . '---';
// echo $arr ['userpassword'] . '---';
// echo $arr ['userrole'] . '<br>';
// } // while (list($id,$name,$pwd,$role)=$stmt->fetch(PDO::FETCH_NUM)){
// echo "{$id}---{$name}---{$pwd}---{$role}<br>";
// } $obj = $stmt->fetch ( PDO::FETCH_OBJ );
var_dump($obj); } catch ( PDOException $e ) {
echo '数据库操作失败:' . $e->getMessage ();
exit ();
}
6.2、fetchall()方法获取数据
调用一次获得结果集中的所有行。并返回二维数组。
示例代码:
$option = array (
PDO::ATTR_PERSISTENT => TRUE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => true
); try {
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
// 查询
$sql = "SELECT * FROM users";
$stmt = $pdo->prepare ( $sql );
$stmt->execute ();
$allRows=$stmt->fetchAll(PDO::FETCH_ASSOC);
echo "一共{$stmt->rowCount()}条记录<br>";
echo "id---account---pwd---role<br>";
foreach ($allRows as $row){
echo "{$row['id']}---{$row['username']}---{$row['userpassword']}---{$row['userrole']}<br>";
}
} catch ( PDOException $e ) {
echo '数据库操作失败:' . $e->getMessage ();
exit ();
}
6.3、setFetchMode()方法获取数据
PDOStatment对象调用setFetchMode()设置fetch和fetchall方法的数据引用方式,fetch和fetchall方法就无需另行单独设置。适用用多次调用fetch和fetchall方法的情况。
6.4、bindColum()方法获取数据
注意点:fetch方法的数据应用方式要设置为PDO::FETCH_BOUND
示例代码:
$option = array (
PDO::ATTR_PERSISTENT => TRUE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => true
); try {
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
// 查询
$sql = "SELECT * FROM users";
$stmt = $pdo->prepare ( $sql );
$stmt->setFetchMode(PDO::FETCH_BOUND); $stmt->execute ();
$stmt->bindColumn(1, $id);
$stmt->bindColumn(2, $name);
$stmt->bindColumn("userpassword", $pwd);
$stmt->bindColumn("userrole", $role);
while($stmt->fetch()){
echo "{$id}---{$name}---{$pwd}---{$role}<br>";
} } catch ( PDOException $e ) {
echo '数据库操作失败:' . $e->getMessage ();
exit ();
}
6.5、获取数据列的属性信息
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
// 查询
$sql = "SELECT * FROM users";
$stmt = $pdo->prepare ( $sql );
$stmt->execute ();
echo 'users表中总共有:'.$stmt->columnCount().'个字段';
var_dump($stmt->getColumnMeta(0));//获取某个字段详细信息
大数据对象的存储
提交文件表单设计:
<form action="action.php" method="post" enctype="multipart/form-data">
<!-- 隐藏域,设置图片大小 -->
<input type="hidden" name="MAX_FILE_SIZE" value="1000000">
<p>选择文件:
<input type="file" name="myfile"></p>
<p>文件描述:<input type="text" name="description"></p>
<p><input type="submit" value="上传"></p>
</form>
文件上传处理
$allowtype = array (
"gif",
"png",
"jpg",
"jpeg"
); // 设置充许上传的类型为gif, png, jpg,jpeg $size = 1000000; // 设置充许大小为1M(1000000字节)以内的文件
$path = "./uploads"; // 设置上传后保存文件的路径,指定当前目录下的uploads目录 /* 判断文件是否可以成功上传到服务器,$_FILES['myfile']['error']值为0表示上传成功 ,其它值则出错 */
if ($_FILES ['myfile'] ['error'] > 0) {
echo '上传错误: ';
switch ($_FILES ['myfile'] ['error']) {
case 1 :
die ( '上传文件大小超出了PHP配置文件中的约定值:upload_max_filesize' );
case 2 :
die ( '上传文件大小超出了表单中的约定值:MAX_FILE_SIZE' );
case 3 :
die ( '文件只被部分上载' );
case 4 :
die ( '没有上传任何文件' );
default :
die ( '未知错误' );
}
} /* 判断上传的文件是否为充许的文件类型 */
// 文件名转数组,第一个元素文件名,第二个元素扩展名
$fileNameArray = explode ( ".", $_FILES ['myfile'] ['name'] );
// 输出文件名数组最后一个元素
$hz = strtolower ( array_pop ( $fileNameArray ) );
/* 通过判断文件的后缀方式,来决定文件是否是充许上传的文件类型 */
if (! in_array ( $hz, $allowtype )) {
die ( "这个后缀是<b>" . $hz . "</b>, 不是充许的文件类型!" );
} /*
* 也可以通过获取上传文件的MIME类型中的主类型和子类型,来限制文件上传的类型
* list($maintype,$subtype)=explode("/",$_FILES['myfile']['type']);
* if ($maintype=="text") { //通过主类型限制不能上传文本文件,例如.txt .html .php等文件
* die('问题: 不能上传文本文件。'); //如果用户上传文本文件则退出程序
* }
*/ /* 判断上传的文件是否为充许尺寸范围内 */
if ($_FILES ['myfile'] ["size"] > $size) {
die ( "超过了充许的<b>{$size}<b>字节大小!" );
} /* 为了系统安全,也为了同名文件会被覆盖,上传后将文件名使用系统定义 */
$filename = date ( "YmdHis" ) . rand ( 100, 999 ) . "." . $hz; /* 判断是否为上传文件 */
if (is_uploaded_file ( $_FILES ['myfile'] ['tmp_name'] )) {
// 移动文件:从临时空间转移到目标位置
// if (! move_uploaded_file ( $_FILES ['myfile'] ["tmp_name"], $path . '/' . $filename )) {
// die ( '问题: 不能将文件移动到指定目录。' );
// }
//图片插入到数据库
$option = array (
PDO::ATTR_PERSISTENT => TRUE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => true
);
try {
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
// 查询
$sql = "INSERT INTO images(contenttype,imagedata,description) VALUES(:contenttype,:imagedata,:description)";
$stmt = $pdo->prepare ( $sql ); $fp=fopen( $_FILES ['myfile'] ["tmp_name"], 'rb');//打开上传的文件 $stmt->bindParam("contenttype", $_FILES ['myfile'] ["type"]);
$stmt->bindParam("imagedata", $fp,PDO::PARAM_LOB);
$stmt->bindParam("description", $_POST['description']);
$stmt->execute ();
} catch ( PDOException $e ) {
echo '数据库操作失败:' . $e->getMessage ();
exit ();
} } else {
die ( "问题: 上传文件{$_FILES['myfile']['name']}不是一个合法文件!" );
} /* 如果文件上传成功则输出 */
//echo "文件{$filename}上传成功,保存在目录{$path}中,大小为{$_FILES['myfile']['size']}字节";
echo "图片保存数据库成功";
读取大对象数据
$option = array (
PDO::ATTR_PERSISTENT => TRUE,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => true
);
try {
$pdo = new PDO ( 'mysql:dbname=football;host=localhost', 'root', 'rootkit', $option );
$sql = "SELECT contenttype,imagedata,description FROM images WHERE id=:id";
$stmt = $pdo->prepare ( $sql );
$stmt->bindParam("id", $id);
$id=2;
$stmt->execute ();
list($type,$lob,$des)=$stmt->fetch();
header("Content-type:$type");
echo $lob;
} catch ( PDOException $e ) {
echo '数据库操作失败:' . $e->getMessage ();
exit ();
}
PDO事务处理
<?php
$pdo = new PDO ( "mysql:host=localhost;dbname=mybank", "root", "rootkit" );
$pdo->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); // 设置异常处理模式 $pdo->setAttribute ( PDO::ATTR_AUTOCOMMIT, 0 ); // 关闭自动提交 try {
$money = 8000; // 转账金额 $pdo->beginTransaction (); // 开始事务 $affected_rows = $pdo->exec ( "UPDATE bank1 SET amount=amount-{$money} WHERE id=1120553244123" ); // 张三账户转出
if ($affected_rows > 0) {
echo "张三账户成功转出{$money}元人民币<br>";
} else {
throw new PDOException ( '张三转出失败' ); // 失败抛出异常,不向下再执行,转到catch区块
} $affected_rows = $pdo->exec ( "UPDATE bank2 SET amount=amount+{$money} WHERE id=2234753244567" ); // 李四账户转入
if ($affected_rows > 0) {
echo "李四账户成功转入{$money}元人民币<br>";
} else {
throw new PDOException ( '李四账户转入失败' ); // 失败抛出异常,不向下再执行,转到catch区块
}
echo "交易成功!";
$pdo->commit (); // 如果执行到此处表示前面两个查询执行成功,整个事务执行成功
} catch ( PDOException $e ) {
echo "交易失败:" . $e->getMessage ();
$pdo->rollback (); // 如果执行到此处理表示事务中的语句出问题了, 整个事务全部撤消
} $pdo->setAttribute ( PDO::ATTR_AUTOCOMMIT, 1 ); //重新开启自动提交
综合练习
需求:世界杯亚洲区赛程信息管理
按照MVC模式实现以下用例:
1、系统角色:管理员,普通用户。
2、用例图
3、登陆界面:
4、管理员登陆后管理界面
5、管理员添加赛程信息
6、管理员修改赛程信息
7、普通用户登陆后操作界面
附表-PDO预定义常量
PDO预定义常量(PDO常量属性)
以下常量由PHP_PDO扩展模块定义,因此只有在本扩展的模块被编译到PHP中,或者在运行时被动态加载后才有效。
注意: PDO使用类常量自PHP 5.1。以前的版本使用的全局常量形式PDO_PARAM_BOOL中。
PDO::PARAM_BOOL (integer) |
表示布尔数据类型。 |
PDO::PARAM_NULL (integer) |
表示 SQL 中的 NULL 数据类型。 |
PDO::PARAM_INT (integer) |
表示 SQL 中的整型。 |
PDO::PARAM_STR (integer) |
表示 SQL 中的 CHAR、VARCHAR 或其他字符串类型。 |
PDO::PARAM_LOB (integer) |
表示 SQL 中大对象数据类型。 |
PDO::PARAM_STMT (integer) |
表示一个记录集类型。当前尚未被任何驱动支持。 |
PDO::PARAM_INPUT_OUTPUT (integer) |
指定参数为一个存储过程的 INOUT 参数。必须用一个明确的 PDO::PARAM_* 数据类型跟此值进行按位或。 |
PDO::FETCH_LAZY (integer) |
指定获取方式,将结果集中的每一行作为一个对象返回,此对象的变量名对应着列名。PDO::FETCH_LAZY 创建用来访问的对象变量名。在 PDOStatement::fetchAll() 中无效。 |
PDO::FETCH_ASSOC (integer) |
指定获取方式,将对应结果集中的每一行作为一个由列名索引的数组返回。如果结果集中包含多个名称相同的列,则PDO::FETCH_ASSOC每个列名只返回一个值。 |
PDO::FETCH_NAMED (integer) |
指定获取方式,将对应结果集中的每一行作为一个由列名索引的数组返回。如果结果集中包含多个名称相同的列,则PDO::FETCH_ASSOC每个列名 返回一个包含值的数组。 |
PDO::FETCH_NUM (integer) |
指定获取方式,将对应结果集中的每一行作为一个由列号索引的数组返回,从第 0 列开始。 |
PDO::FETCH_BOTH (integer) |
指定获取方式,将对应结果集中的每一行作为一个由列号和列名索引的数组返回,从第 0 列开始。 |
PDO::FETCH_OBJ (integer) |
指定获取方式,将结果集中的每一行作为一个属性名对应列名的对象返回。 |
PDO::FETCH_BOUND (integer) |
指定获取方式,返回 TRUE 且将结果集中的列值分配给通过 PDOStatement::bindParam() 或 PDOStatement::bindColumn() 方法绑定的 PHP 变量。 |
PDO::FETCH_COLUMN (integer) |
指定获取方式,从结果集中的下一行返回所需要的那一列。 |
PDO::FETCH_CLASS (integer) |
指定获取方式,返回一个所请求类的新实例,映射列到类中对应的属性名。 注意: 如果所请求的类中不存在该属性,则调用 __set() 魔术方法 |
PDO::FETCH_INTO (integer) |
指定获取方式,更新一个请求类的现有实例,映射列到类中对应的属性名。 |
PDO::FETCH_FUNC (integer) |
允许在运行中完全用自定义的方式处理数据。(仅在 PDOStatement::fetchAll() 中有效)。 |
PDO::FETCH_GROUP (integer) |
根据值分组返回。通常和 PDO::FETCH_COLUMN 或 PDO::FETCH_KEY_PAIR 一起使用。 |
PDO::FETCH_UNIQUE (integer) |
只取唯一值。 |
PDO::FETCH_KEY_PAIR (integer) |
获取一个有两列的结果集到一个数组,其中第一列为键名,第二列为值。自 PHP 5.2.3 起可用。 |
PDO::FETCH_CLASSTYPE (integer) |
根据第一列的值确定类名。 |
PDO::FETCH_SERIALIZE (integer) |
类似 PDO::FETCH_INTO ,但是以一个序列化的字符串表示对象。自 PHP 5.1.0 起可用。从 PHP 5.3.0 开始,如果设置此标志,则类的构造函数从不会被调用。 |
PDO::FETCH_PROPS_LATE (integer) |
设置属性前调用构造函数。自 PHP 5.2.0 起可用。 |
PDO::ATTR_AUTOCOMMIT (integer) |
如果此值为 FALSE ,PDO 将试图禁用自动提交以便数据库连接开始一个事务。 |
PDO::ATTR_PREFETCH (integer) |
设置预取大小来为你的应用平衡速度和内存使用。并非所有的数据库/驱动组合都支持设置预取大小。较大的预取大小导致性能提高的同时也会占用更多的内存。 |
PDO::ATTR_TIMEOUT (integer) |
设置连接数据库的超时秒数。 |
PDO::ATTR_ERRMODE (integer) |
关于此属性的更多信息请参见 错误及错误处理 部分。 |
PDO::ATTR_SERVER_VERSION (integer) |
此为只读属性;返回 PDO 所连接的数据库服务的版本信息。 |
PDO::ATTR_CLIENT_VERSION (integer) |
此为只读属性;返回 PDO 驱动所用客户端库的版本信息。 |
PDO::ATTR_SERVER_INFO (integer) |
此为只读属性。返回一些关于 PDO 所连接的数据库服务的元信息。 |
PDO::ATTR_CONNECTION_STATUS (integer) |
|
PDO::ATTR_CASE (integer) |
用类似 PDO::CASE_* 的常量强制列名为指定的大小写。 |
PDO::ATTR_CURSOR_NAME (integer) |
获取或设置使用游标的名称。当使用可滚动游标和定位更新时候非常有用。 |
PDO::ATTR_CURSOR (integer) |
选择游标类型。 PDO 当前支持 PDO::CURSOR_FWDONLY 和 PDO::CURSOR_SCROLL。一般为 PDO::CURSOR_FWDONLY,除非确实需要一个可滚动游标。 |
PDO::ATTR_DRIVER_NAME (string) |
返回驱动名称。 使用 PDO::ATTR_DRIVER_NAME 的例子: <?php if ($db->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql') { echo "Running on mysql; doing something mysql specific here\n"; } ?> |
PDO::ATTR_ORACLE_NULLS (integer) |
在获取数据时将空字符串转换成 SQL 中的 NULL 。 |
PDO::ATTR_PERSISTENT (integer) |
请求一个持久连接,而非创建一个新连接。关于此属性的更多信息请参见 连接与连接管理 。 |
PDO::ATTR_STATEMENT_CLASS (integer) |
|
PDO::ATTR_FETCH_CATALOG_NAMES (integer) |
将包含的目录名添加到结果集中的每个列名前面。目录名和列名由一个小数点分开(.)。此属性在驱动层面支持,所以有些驱动可能不支持此属性。 |
PDO::ATTR_FETCH_TABLE_NAMES (integer) |
将包含的表名添加到结果集中的每个列名前面。表名和列名由一个小数点分开(.)。此属性在驱动层面支持,所以有些驱动可能不支持此属性。 |
PDO::ATTR_STRINGIFY_FETCHES (integer) |
|
PDO::ATTR_MAX_COLUMN_LEN (integer) |
|
PDO::ATTR_DEFAULT_FETCH_MODE (integer) |
自 PHP 5.2.0 起可用。 |
PDO::ATTR_EMULATE_PREPARES (integer) |
自 PHP 5.1.3 起可用。 |
PDO::ERRMODE_SILENT (integer) |
如果发生错误,则不显示错误或异常。希望开发人员显式地检查错误。此为默认模式。关于此属性的更多信息请参见 错误与错误处理 。 |
PDO::ERRMODE_WARNING (integer) |
如果发生错误,则显示一个 PHP E_WARNING 消息。关于此属性的更多信息请参见 错误与错误处理。 |
PDO::ERRMODE_EXCEPTION (integer) |
如果发生错误,则抛出一个 PDOException 异常。关于此属性的更多信息请参见 错误与错误处理。 |
PDO::CASE_NATURAL (integer) |
保留数据库驱动返回的列名。 |
PDO::CASE_LOWER (integer) |
强制列名小写。 |
PDO::CASE_UPPER (integer) |
强制列名大写。 |
PDO::NULL_NATURAL (integer) |
|
PDO::NULL_EMPTY_STRING (integer) |
|
PDO::NULL_TO_STRING (integer) |
|
PDO::FETCH_ORI_NEXT (integer) |
在结果集中获取下一行。仅对可滚动游标有效。 |
PDO::FETCH_ORI_PRIOR (integer) |
在结果集中获取上一行。仅对可滚动游标有效。 |
PDO::FETCH_ORI_FIRST (integer) |
在结果集中获取第一行。仅对可滚动游标有效。 |
PDO::FETCH_ORI_LAST (integer) |
在结果集中获取最后一行。仅对可滚动游标有效。 |
PDO::FETCH_ORI_ABS (integer) |
根据行号从结果集中获取需要的行。仅对可滚动游标有效。 |
PDO::FETCH_ORI_REL (integer) |
根据当前游标位置的相对位置从结果集中获取需要的行。仅对可滚动游标有效。 |
PDO::CURSOR_FWDONLY (integer) |
创建一个只进游标的 PDOStatement 对象。此为默认的游标选项,因为此游标最快且是 PHP 中最常用的数据访问模式。 |
PDO::CURSOR_SCROLL (integer) |
创建一个可滚动游标的 PDOStatement 对象。通过 PDO::FETCH_ORI_* 常量来控制结果集中获取的行。 |
PDO::ERR_NONE (string) |
对应 SQLSTATE '00000',表示 SQL 语句没有错误或警告地成功发出。当用 PDO::errorCode() 或 PDOStatement::errorCode() 来确定是否有错误发生时,此常量非常方便。在检查上述方法返回的错误状态代码时,会经常用到。 |
PDO::PARAM_EVT_ALLOC (integer) |
分配事件 |
PDO::PARAM_EVT_FREE (integer) |
解除分配事件 |
PDO::PARAM_EVT_EXEC_PRE (integer) |
执行一条预处理语句之前触发事件。 |
PDO::PARAM_EVT_EXEC_POST (integer) |
执行一条预处理语句之后触发事件。 |
PDO::PARAM_EVT_FETCH_PRE (integer) |
从一个结果集中取出一条结果之前触发事件。 |
PDO::PARAM_EVT_FETCH_POST (integer) |
从一个结果集中取出一条结果之后触发事件。 |
PDO::PARAM_EVT_NORMALIZE (integer) |
在绑定参数注册允许驱动程序正常化变量名时触发事件。 |
PHP17 PDO的更多相关文章
- 比Mysqli操作数据库更简便的方式 。PDO
下面来说一下PDO 先画一张图来了解一下 mysqli是针对mysql这个数据库扩展的一个类 PDO是为了能访问更多数据库 如果出现程序需要访问其他数据库的话就可以用PDO来做 PDO数据访问抽象层1 ...
- pdo的使用
PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口. PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据. PDO随 ...
- PHP中PDO事务的使用方法
事务 (Transaction) 是操作数据库中很重要的一个功能, 它可以让你预定一条, 或者一系列 SQL 语句, 然后一起执行. 在执行的过程中, 如果其中的某条执行失败, 可以回滚所有已更改的操 ...
- PDO连接mysql数据库
1.PDO简介 PDO(PHP Data Object) 是PHP 5 中加入的东西,是PHP 5新加入的一个重大功能,因为在PHP 5以前的php4/php3都是一堆的数据库扩展来跟各个数据库的连接 ...
- PDO概念 分析 练习
PDO 翻译过来叫做数据访问抽象层 它是一个数据访问的层面,实际上是一个类,也就是说所有操作数据库的代码,都是通过这个层面完成的 该图好理解大概就是这样一种模式 现在考虑的是能不能使用同一个类,上层代 ...
- PDO
'PDO'是数据访问抽象层'用mysqli类找到mysqli驱动根据驱动操作mysqli数据库'其他类找到sqlserver驱动根据驱动操作sqlserve数据库'PDO 访问其他数据库 PDO的用法 ...
- 前端学PHP之PDO预处理语句
× 目录 [1]定义 [2]准备语句 [3]绑定参数[4]执行查询[5]获取数据[6]大数据对象 前面的话 本来要把预处理语句和前面的基础操作写成一篇的.但是,由于博客园的限制,可能是因为长度超出,保 ...
- 前端学PHP之PDO基础操作
× 目录 [1]创建PDO [2]使用PDO [3]事务处理 前面的话 PDO(php data object)扩展类库为php访问数据库定义了轻量级的.一致性的接口,它提供了一个数据库访问抽象层,这 ...
- CANopen学习——PDO
查找资料时,发现一个很好的博客,博主剖析的通俗易懂 http://www.cnblogs.com/winshton/p/4897556.html PDO定义: 过程数据对象,用来传输实时数据.因为 ...
随机推荐
- NOI前总结:点分治
点分治: 点分治的题目基本一样,都是路径计数. 其复杂度的保证是依靠 $O(n)$ 找重心的,每一次至少将问题规模减小为原先的$1/2$. 找重心我喜欢$BFS$防止爆栈. int Root(int ...
- Vue-i18n实现语言切换
方法1 Vue — i18n 国际化 全局配置 安 装 1.直接引入js文件 <script src="https://unpkg.com/vue/dist/vue.js"& ...
- rbenv的使用
创建: 2017/09/05 更新: 2018/02/03 增加更新rbenv和获取list没有的版本 更新: 2018/02/25 把path里面[个人主机名]全部替换为[主机名] 更新: 2018 ...
- J20170403-gg
うっすら 微微的,薄薄的 グラデーション 渐变 ぼかし(暈し) 晕色 由浓到淡渐变上色的东西 シャドウ 影子,阴影 ドメイン 域名 サブドメイン 子域名
- 洛谷 - P2657 - windy数 - 数位dp
https://www.luogu.org/problemnew/show/P2657 不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. 这道题是个显然到不能再显然的数位dp了. 来个 ...
- HDOJ1864(水的可怜)
注意这句话:精确到小数点后两位如果是小数点的话 HDOJ1864 #include<stdio.h> #include<iostream> #include<algori ...
- bzoj 2560: 串珠子【状压dp】
正难则反,设g[s]为集合s不一定联通的方案数,这个很好求,把边数+1乘起来即可,f[s]为s一定联通的方案数 f考虑容斥,就是g[s]-Σf[nw]*g[s^nw],nw是s的子集,这样就减掉了不联 ...
- bzoj 1049: [HAOI2006]数字序列【dp+二分+瞎搞】
第一问明显就是用b[i]=a[i]-i来做最长不下降子序列 然后第二问,对于一对f[i]=f[j]+1的(i,j),中间的数一定要改的,并且是等于b[i]或者b[j],我不会证,然后因为是随机数据,所 ...
- poj 1723 Soldiers【中位数】By cellur925
题目传送门 题目大意:平面上有n个士兵,给出每个士兵的坐标,求出使这些士兵站好所需要的最少移动步数.站好要求:所有士兵y相等,x相邻.即达到 (x,y), (x+1, y), (x+2,y)……的状态 ...
- NOIp2017真题模拟赛 By cellur925
果然我还是最菜的==不接受反驳 (先考了day2喵喵喵) Day2 T1:奶酪 期望得分:100分 实际得分:100分 考察:并查集 思路:这题其实之前做过了==.思路还是比较清晰的,读入时预处理出可 ...