首页 php教程 php手册 PHP PDO访问数据库

PHP PDO访问数据库

Jun 06, 2016 pm 07:59 PM
p pdo php 为什么 使用 数据库 访问

为什么你应该使用PHP PDO访问数据库 许多PHP程序员学习过如歌使用MySQL或MySQL扩展来访问数据库. 不过,自PHP 5.1版本以来,一个更好的解决方案出现了. PHP Data Objects (PDO) 提供了让你更有{productive}的准备{statements},处理对象的方法. PDO 简介 “PDO

为什么你应该使用PHP PDO访问数据库

许多PHP程序员学习过如歌使用MySQL或MySQL扩展来访问数据库. 不过,自PHP 5.1版本以来,一个更好的解决方案出现了. PHP Data Objects (PDO) 提供了让你更有{productive}的准备{statements},处理对象的方法.


PDO 简介

“PDO – PHP Data Objects – is a database access layer providing a uniform method of access to multiple databases.”

它不受数据库特定语法限制, 但它可以让切换数据库和平台的过程更无痛,更简洁的切换数据库连接字符串.

PHP PDO访问数据库

这个教程并是一个完全的SQL入门. 它主要是为了帮助那些已经在使用MySQL或MySQLi扩展的人们过渡到更加强大、兼容性更好的PDO.

数据库支持

这个扩展能支持任何为PDO设计了驱动的数据库. 在写这篇文章的时候,以下数据库已经被支持:

  • PDO_DBLIB ( FreeTDS / Microsoft SQL Server / Sybase )
  • PDO_FIREBIRD ( Firebird/Interbase 6 )
  • PDO_IBM ( IBM DB2 )
  • PDO_INFORMIX ( IBM Informix Dynamic Server )
  • PDO_MYSQL ( MySQL 3.x/4.x/5.x )
  • PDO_OCI ( Oracle Call Interface )
  • PDO_ODBC ( ODBC v3 (IBM DB2, unixODBC and win32 ODBC) )
  • PDO_PGSQL ( PostgreSQL )
  • PDO_SQLITE ( SQLite 3 and SQLite 2 )
  • PDO_4D ( 4D )

所有这些驱动都没有被您的系统预装,这里有一种快速的方式来找到您需要的驱动:

print_r(PDO::getAvailableDrivers());


连接

不同的数据库可能在连接方法上有那么一点点的不同. 下面,我们将介绍几种常见的数据库的连接方法. 你将会注意到前三种看起来差不多, 不过像SQLite之类的语言就有他自己独特的语法.

PHP PDO访问数据库

try {
# MS SQL Server and Sybase with PDO_DBLIB
$DBH = new PDO(“mssql:host=$host;dbname=$dbname, $user, $pass”);
$DBH = new PDO(“sybase:host=$host;dbname=$dbname, $user, $pass”);

# MySQL with PDO_MYSQL
$DBH = new PDO(“mysql:host=$host;dbname=$dbname”, $user, $pass);

# SQLite Database
$DBH = new PDO(“sqlite:my/database/path/database.db”);
}
catch(PDOException $e) {
echo $e->getMessage();
}

请注意try/catch代码块 – 您应该始终将您 PDO 的操作封装在一个 try/catch 代码块内并使用异常机制 .通常你只会使用单个连接 – 下面将为您介绍它的语法.

下文中出现的 $DBH 意思是 ‘database handle’.

你可以通过把handle设置为null来关闭任何数据库连接.

# close the connection

$DBH = null;

你可以从 PHP.net 获取更多关于特点数据库的选项和连接字串(connection strings)的信息


异常处理

PDO 可以使用异常(Exceptions)来处理错误,这意味你需要把{处理PDO的}包括在一个try/catch代码块. 你也可以通过设置错误模式(error mode attribute)强制PDO在您最近创建的数据库连接上使用这三种错误模式中的一种. 以下提供了语法:

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );

$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

不过不管您设置什么错误模式, 错误的连接总会产生一个异常, 所以您应该在创建一个数据库时包含一个try/catch代码块.

PDO::ERRMODE_SILENT

这是默认的错误模式. 如果您使用了这种错误模式, 你将像您用mysql或mysqli扩展的时候那样自己检查错误. 这里还有两种更理想的符合[[DRY programming]]思想的方法.

PDO::ERRMODE_WARNING

这种模式将会发出(issue)一个标准的PHP warning,然后继续执行程序. 这种方法在调试时会很有用.

PDO::ERRMODE_EXCEPTION

这也许是人们在大多数情况下希望使用的模式. 它抛出(fire)一个异常, 允许你优雅的处理错误并且隐藏那些可能会导致安全风险的数据. 这里是一个处理异常的实例:

# connect to the database
try {
$DBH = new PDO(“mysql:host=$host;dbname=$dbname”, $user, $pass);
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

# UH-OH! Typed DELECT instead of SELECT!
$DBH->prepare(‘DELECT name FROM people’);
}
catch(PDOException $e) {
echo “I’m sorry, Dave. I’m afraid I can’t do that.”;
file_put_contents(‘PDOErrors.txt’, $e->getMessage(), FILE_APPEND);
}

上面是一个在select statement中的内部错误; 这将会引发一个异常. 这段异常处理代码将会把错误详情发送到一个日志文件中, 然后显示一个友好的(当然,友不友好随你便)消息给用户.


插入、更新数据

插入新数据、或更新一个已经存在的数据,是最常见的数据库操作之一. PDO提供了一种[[normally a two-step process]]. 本节中介绍的所有内容同样适用于 UPDATE 和 INSERT 操作.

PHP PDO访问数据库

下面是一个最基本的插入的例子:

# STH means “Statement Handle”

$STH = $DBH->prepare(“INSERT INTO folks ( first_name ) values ( ‘Cathy’ )”);

$STH->execute();

您也可以直接使用exec()方法完成相同的操作(PS:使用exec()方法可以减少一个调用). 在大多数情况下,您可能会多次调用这个方法, 所以呢, 您可以享受到prepared statements带来的好处. 甚至如果您只想调用它一次, 使用prepared statements will 也会帮您挡住 SQL injection 攻击.

Prepared Statements

使用 prepared statements 将帮助您防止 SQL injection 的危险.

Prepared statement的语句是只需要发送数据到服务器的预编译 SQL 语句, 它具有自动处理数据以免受 SQL injection 攻击的优点。

您可以通过在您的SQL语句中包含占位符来使用 prepared statement . 这里有三个例子: 一个没有占位符的, 一个有未命名占位符(Unnamed Placeholders)的, 和一个有命名占位符(Named Placeholders)的.

# no placeholders – ripe for SQL Injection!
$STH = $DBH->(“INSERT INTO folks (name, addr, city) values ($name, $addr, $city)”);

# unnamed placeholders
$STH = $DBH->(“INSERT INTO folks (name, addr, city) values (?, ?, ?);

# named placeholders
$STH = $DBH->(“INSERT INTO folks (name, addr, city) value (:name, :addr, :city)”);

您可能想避免使用第一种方法; 下面为您提供了它们直接的比较. 选择未命名占位符或命名占位符将会影响您如何为这些语句设置数据.

未命名占位符(Unnamed Placeholders)

# assign variables to each place holder, indexed 1-3
$STH->bindParam(1, $name);
$STH->bindParam(2, $addr);
$STH->bindParam(3, $city);

# insert one row
$name = “Daniel”
$addr = “1 Wicked Way”;
$city = “Arlington Heights”;
$STH->execute();

# insert another row with different values
$name = “Steve”
$addr = “5 Circle Drive”;
$city = “Schaumburg”;
$STH->execute();

只需两步!首先,我们为不同的占位符(Placeholder)绑定变量 (lines 2-4). 然后,我们为那些占位符(Placeholder)赋值然后执行查询. 要想发送另外的一组数据,只需要改变那些变量的值,然后再执行即可.

(译注: 原文在第一步与第二布均使用了assign来描述过程)

这个使用很多参数的方法似乎有点麻烦?如果您的数据存储在数组中,有一个简单的方法:

# the data we want to insert
$data = array(‘Cathy’, ’9 Dark and Twisty Road’, ‘Cardiff’);

$STH = $DBH->(“INSERT INTO folks (name, addr, city) values (?, ?, ?);
$STH->execute($data);

这很简单,不是吗?

在数组中的数据等同于占位符。 $data[0]对应第一个占位符,$data[1]第二个,依此类推,但如果您的数组索引并未排序,这将无法正常工作,您将需要重新索引这个数组.

命名占位符(Named Placeholders)

您可能已经猜到语法了,下面给出了一个例子:

# the first argument is the named placeholder name – notice named
# placeholders always start with a colon.
$STH->bindParam(‘:name’, $name);

您也可以在这里使用一个快捷方式,但它可以和关联数组一起使用.

# the data we want to insert
$data = array( ‘name’ => ‘Cathy’, ‘addr’ => ’9 Dark and Twisty’, ‘city’ => ‘Cardiff’ );

# the shortcut!
$STH = $DBH->(“INSERT INTO folks (name, addr, city) value (:name, :addr, :city)”);
$STH->execute($data);

你的数组中的键不需要以一个冒号开始,但是必须符合指定的占位符。如果你有一个二维数组(就是数组中的数组),您可以遍历它们,只需调用执行的每个数据的数组。

另一个命名占位符不错的特点是直接可以插入对象到您的数据库,如果命名的属性匹配字段的话.下面是一个例子对象:

# a simple object
class person {
public $name;
public $addr;
public $city;

function __construct($n,$a,$c) {
$this->name = $n;
$this->addr = $a;
$this->city = $c;
}
# etc …
}

$cathy = new person(‘Cathy’,’9 Dark and Twisty’,'Cardiff’);

# here’s the fun part:
$STH = $DBH->(“INSERT INTO folks (name, addr, city) value (:name, :addr, :city)”);
$STH->execute((array)$cathy);

在执行中,对象被转换为一个数组.对象的属性被视为数组中的一个键. By casting the object to an array in the execute, the properties are treated as array keys.


选择数据

PHP PDO访问数据库

数据通过fetch()方法获得, {一种应用于陈述式句柄的方法}. 在使用fetch之间, 您最好告诉PDO您喜欢取得数据的样子. 您有以下几个选择:

  • PDO::FETCH_ASSOC: 返回一个包含列名索引的数组
  • PDO::FETCH_BOTH (default): 返回一个由同时包含列名和数字索引的数组
  • PDO::FETCH_BOUND: 通过 ->bindColumn() 方法将列的值赋到变量上。
  • PDO::FETCH_CLASS:列的值赋给指定对象的属性里。如果指定的属性不存在,会自动创建。
  • PDO::FETCH_INTO: 更新一个已经存在的命名对象的实例
  • PDO::FETCH_LAZY: 结合 了PDO::FETCH_BOTH,PDO::FETCH_OBJ,在它们被调用时创建对象变量
  • PDO::FETCH_NUM: 返回一个由同时包含列数字索引的数组
  • PDO::FETCH_OBJ: fanhuire返回一个有对应的列名的属性的匿名对象

在现实中,大多数情况下会使用以下三种: FETCH_ASSOC, FETCH_CLASS, FETCH_OBJ. 您需要使用以下语法设置获取类型:

$STH->setFetchMode(PDO::FETCH_ASSOC);

您也可以直接在fetch()方法中设置获取模式.

FETCH_ASSOC

这种模式创建一个按列名索引的关联数组.这应该会让用过MySQL/MySQLi扩展的人感到亲切.这里有一个使用这种方法选择数据的例子.

# using the shortcut ->query() method here since there are no variable
# values in the select statement.
$STH = $DBH->query(‘SELECT name, addr, city from folks’);

# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_ASSOC);

while($row = $STH->fetch()) {
echo $row['name'] . “n”;
echo $row['addr'] . “n”;
echo $row['city'] . “n”;
}

这个 while 循环将在获取完所有数据后停止.{The while loop will continue to go through the result set one row at a time until complete.}

FETCH_OBJ

这种模式为每一行数据创建一个标准类,下面是一个例子:

# creating the statement
$STH = $DBH->query(‘SELECT name, addr, city from folks’);

# setting the fetch mode
$STH->setFetchMode(PDO::FETCH_OBJ);

# showing the results
while($row = $STH->fetch()) {
echo $row->name . “n”;
echo $row->addr . “n”;
echo $row->city . “n”;
}

FETCH_CLASS

您的对象的属性应该在constructor被调用前设置!这一点很重要!

这种模式允许你直接将获取的数据发送到您选择的类中.当您使用FETCH_CLASS时,您的对象的属性应该在constructor被调用前设置。读一遍,它是重要的。如果属性相匹配的列名不存在,这些属性将被创建,(公共)为您。

这意味着如果你需要转换后出来的数据,它可以通过你的对象自动为转换.

举个列子,假设的情况下该地址必须为特定格式,我们可以通过constructor上做到这一点,下面是一个例子:

class secret_person {
public $name;
public $addr;
public $city;
public $other_data;

function __construct($other = ”) {
$this->address = preg_replace(‘/[a-z]/’, ‘x’, $this->address);
$this->other_data = $other;
}
}

OK,再让我们看看效果如何?

$STH = $DBH->query(‘SELECT name, addr, city from folks’);
$STH->setFetchMode(PDO::FETCH_CLASS, ‘secret_person’);

while($obj = $STH->fetch()) {
echo $obj->addr;
}

如果地址是,‘5 Rosebud,’ 您将会在输出中看到 ‘5 Rxxxxxx’. 当然,可能有些情况下,您希望在constructor函数在数据被赋值之前调用.PDO也可以做到~

$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, ‘secret_person’);

现在,当你使用这个模式(PDO::FETCH_PROPS_LATE)的地址不会被遮,constructor会被首先调用然后再赋值.

最后,如果你真的需要,你可以在使用PDO获取数据到对象时,将参数传递给构造函数:

$STH->setFetchMode(PDO::FETCH_CLASS, ‘secret_person’, array(‘stuff’));

如果你需要传递不同的数据到每个对象的构造函数,你可以设置在fetch方法内设置模式法模式:

$i = 0;
while($rowObj = $STH->fetch(PDO::FETCH_CLASS, ‘secret_person’, array($i))) {
// do stuff
$i++
}


其他有用的方法

虽然 PDO 并没有面面俱到的(这扩展可不小!), 这里仍还还有一些您想知道的方法.

$DBH->lastInsertId();

lastInsertId()方法始终调用数据库句柄,而不是表达式的句柄,并且会返回该数据库连接上一次插入语句的自增ID.

$DBH->exec(‘DELETE FROM folks WHERE 1′);

$DBH->exec(“SET time_zone = ‘-8:00′”);

exec()方法用于那些不能返回数据或不影响行的操作. 上面是两种调用exec()方法的例子.

$safe = $DBH->quote($unsafe);

quote() 方法将字符转义为安全的字符以便在查询中使用. 如果您不使用已经准备号的语句,您可以用此方法>。

$rows_affected = $STH->rowCount();

rowCount() 方法返回一个表明被一个操作影响的行数的整数(简直是废话,难不成还是浮点数?). 更具这个错误报告(http://bugs.php.net/40822) ,在最近的一个PDO版本上这个方法不能够很好的与SELECT语句工作. 如果您遇到了这个问题而不想升级PHP的话, 你可以用以下的方法来替代它:

$sql = “SELECT COUNT(*) FROM folks”;
if ($STH = $DBH->query($sql)) {
# check the row count
if ($STH->fetchColumn() > 0) {

# issue a real select here, because there’s data!
}
else {
echo “No rows matched the query.”;
}
}


结尾

我希望这篇文章能帮助您从mysql和mysqli扩展迁移至PDO.您有啥想法?现在想迁移到PDO么?

英文原文:http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1664
14
CakePHP 教程
1423
52
Laravel 教程
1318
25
PHP教程
1269
29
C# 教程
1248
24
作曲家:通过AI的帮助开发PHP 作曲家:通过AI的帮助开发PHP Apr 29, 2025 am 12:27 AM

AI可以帮助优化Composer的使用,具体方法包括:1.依赖管理优化:AI分析依赖关系,建议最佳版本组合,减少冲突。2.自动化代码生成:AI生成符合最佳实践的composer.json文件。3.代码质量提升:AI检测潜在问题,提供优化建议,提高代码质量。这些方法通过机器学习和自然语言处理技术实现,帮助开发者提高效率和代码质量。

session_start()函数的意义是什么? session_start()函数的意义是什么? May 03, 2025 am 12:18 AM

session_start()iscucialinphpformanagingusersessions.1)ItInitiateSanewsessionifnoneexists,2)resumesanexistingsessions,and3)setsasesessionCookieforContinuityActinuityAccontinuityAcconActInityAcconActInityAcconAccRequests,EnablingApplicationsApplicationsLikeUseAppericationLikeUseAthenticationalticationaltication and PersersonalizedContentent。

php框架laravel和yii区别是什么 php框架laravel和yii区别是什么 Apr 30, 2025 pm 02:24 PM

Laravel和Yii的主要区别在于设计理念、功能特性和使用场景。1.Laravel注重开发的简洁和愉悦,提供丰富的功能如EloquentORM和Artisan工具,适合快速开发和初学者。2.Yii强调性能和效率,适用于高负载应用,提供高效的ActiveRecord和缓存系统,但学习曲线较陡。

给MySQL表添加和删除字段的操作步骤 给MySQL表添加和删除字段的操作步骤 Apr 29, 2025 pm 04:15 PM

在MySQL中,添加字段使用ALTERTABLEtable_nameADDCOLUMNnew_columnVARCHAR(255)AFTERexisting_column,删除字段使用ALTERTABLEtable_nameDROPCOLUMNcolumn_to_drop。添加字段时,需指定位置以优化查询性能和数据结构;删除字段前需确认操作不可逆;使用在线DDL、备份数据、测试环境和低负载时间段修改表结构是性能优化和最佳实践。

H5:HTML5的关键改进 H5:HTML5的关键改进 Apr 28, 2025 am 12:26 AM

HTML5带来了五个关键改进:1.语义化标签提升了代码清晰度和SEO效果;2.多媒体支持简化了视频和音频嵌入;3.表单增强简化了验证;4.离线与本地存储提高了用户体验;5.画布与图形功能增强了网页的可视化效果。

如何使用MySQL的函数进行数据处理和计算 如何使用MySQL的函数进行数据处理和计算 Apr 29, 2025 pm 04:21 PM

MySQL函数可用于数据处理和计算。1.基本用法包括字符串处理、日期计算和数学运算。2.高级用法涉及结合多个函数实现复杂操作。3.性能优化需避免在WHERE子句中使用函数,并使用GROUPBY和临时表。

MySQL的字符集和排序规则如何配置 MySQL的字符集和排序规则如何配置 Apr 29, 2025 pm 04:06 PM

在MySQL中配置字符集和排序规则的方法包括:1.设置服务器级别的字符集和排序规则:SETNAMES'utf8';SETCHARACTERSETutf8;SETCOLLATION_CONNECTION='utf8_general_ci';2.创建使用特定字符集和排序规则的数据库:CREATEDATABASEexample_dbCHARACTERSETutf8COLLATEutf8_general_ci;3.创建表时指定字符集和排序规则:CREATETABLEexample_table(idINT

怎样在C  中处理传感器数据? 怎样在C 中处理传感器数据? Apr 28, 2025 pm 10:00 PM

C 适合处理传感器数据,因为其高性能和低级控制能力。具体步骤包括:1.数据采集:通过硬件接口获取数据。2.数据解析:将原始数据转换为可用信息。3.数据处理:进行滤波和平滑处理。4.数据存储:保存数据到文件或数据库。5.实时处理:确保代码的高效性和低延迟。

See all articles