相关学习资料
http://www.php.net/manual/zh/refs.database.php http://www.php.net/manual/zh/internals2.pdo.php http://bbs.phpchina.com/thread-184537-1-1.html http://www.metsky.com/archives/660.html http://www.phpbuilder.com/ http://www.w3school.com.cn/php/php_db_odbc.asp https://www.ibm.com/developerworks/cn/opensource/os-php-odbc/ http://blog.csdn.net/deflag/article/details/743597 http://www.informit.com/articles/article.aspx?p=31839&seqNum=3 http://zh.wikipedia.org/wiki/Berkeley_DB http://blog.csdn.net/zuiaituantuan/article/details/5996376
目录
1. PHP数据库驱动简介 2. PHP连接数据库的不同方式
1. PHP数据库驱动简介
驱动是一段设计用来于一种特定类型的数据库服务器进行交互的软件代码。驱动可能会调用一些库。类似于Java中的数据库驱动的概念
1. JDBC-ODPC桥: 它将JDBC API映射到ODPC API。再让JDBC-ODPC调用数据库本地驱动代码(也就是数据库厂商提供的数据库操作二进制代码库,例如Oracle中的oci.dll) 2. 本地API驱动 直接将JDBC API映射成数据库特定的客户端API,即通过客户端加载数据库厂商提供的本地代码库(C/C++等) 3. 网络协议驱动(主流) 这种类型的驱动给客户端提供了一个网络API,客户端上的JDBC驱动程序使用套接字(Socket)来调用服务器上的中间件程序,后者在将其请求转化为所需的具体API调用。 4. 本地协议驱动(主流) 这种类型的驱动使用Socket,直接在客户端和数据库间通信。它是一种直接与数据库实例交互的JDBC 这种驱动是智能的,它知道数据库使用的底层协议,也是目前最主流使用的JDBC驱动,我们本章的重点就是它
而对于PHP来说,同样主流使用的也是网络协议驱动、本地协议驱动,即MySQL客户端库、MySQL Native驱动库。
这些库实现了用于和MySQL数据库服务器进行交互的底层协议。
数据库驱动位于PHP和数据库进行通信的最底层,不同的数据库厂商都会在基于某个框架的前提下实现自己的驱动,用以提供基本功能、以及特定数据库的高级功能。
在驱动层之上是"连接器"、或者是适配器抽象层,用于PHP代码和数据库进行连接,程序员可以使用PDO(PHP Database Object)、或者直接使用扩展接口(mysql、mysqli)这些暴露出来的API与底层数据库进行通信。
数据库厂商提供的底层数据库驱动
mysql: http://www.mysql.com/products/connector/ oracle: http://www.oracle.com/technetwork/indexes/downloads/index.html#database sqlserver: http://msdn.microsoft.com/zh-cn/library/cc296170(SQL.90).aspx
...
文件型数据库
文件型是一种基于文件的数据库引擎,而且使用文件I/O(输入/输出)函数来存储和读取来自磁盘上文件的数据库。它普遍也比关系型数据库(例如Mysql)小很多很多(例如典型的文件型数据库
SQLite命令行版本的大小小于200KB),同时,文件型数据库而且支持你所熟悉的大部分SQL命令,同时具有易于携带的特点
接下来,我们以上面这张大图作为开始,逐一学习PHP连接数据库的不同方式、以及它们在不同业务场景下的优缺点
2. PHP连接数据库的不同方式
0x1: 使用扩展API接口与数据库通信
PHP代码是由一个核心,一些可选扩展组成了核心功能。PHP 的MySQL相关扩展,比如mysqli,mysql都是基于PHP扩展框架实现的。
扩
展一个典型的作用就是暴露一个API给PHP程序员,允许扩展自己的功能可以被程序员使用。当然,也有一部分基于PHP扩展框架
开发的扩展不会给PHP程序员暴露API接口。比如说PDO
MySQL驱动扩展,就没有向PHP程序员暴露API接口,但是向它上层的PDO层提供了一个接口。
关于PHP扩展的编写请参阅另一篇博文 http://www.cnblogs.com/LittleHann/p/3562259.html
在实际编程中,使用频度最多的还是以扩展API的方式去连接数据库
extension=php_mysql.dll
这
是设计开发允许PHP应用与MySQL数据库交互的早期扩展。mysql扩展提供了一个面向过程的接口,并且是针对MySQL4.1.3或更早版本设计
的。因此,这个扩展虽然可以与MySQL4.1.3或更新的数据库服务端
进行交互,但并不支持后期MySQL服务端提供的一些特性
mysql扩展的源代码在PHP扩展目录ext/mysql下
<?php // 连接、选择数据库 $link = mysql_connect(‘mysql_host‘, ‘mysql_user‘, ‘mysql_password‘) or die(‘Could not connect: ‘ . mysql_error()); echo ‘Connected successfully‘; mysql_select_db(‘my_database‘) or die(‘Could not select database‘); // 执行 SQL 查询 $query = ‘SELECT * FROM my_table‘; $result = mysql_query($query) or die(‘Query failed: ‘ . mysql_error()); // 以 HTML 打印查询结果 echo "<table>\n"; while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) { echo "\t<tr>\n"; foreach ($line as $col_value) { echo "\t\t<td>$col_value</td>\n"; } echo "\t</tr>\n"; } echo "</table>\n"; // 释放结果集 mysql_free_result($result); // 关闭连接 mysql_close($link); ?>
extension=php_mysqli.dll
mysqli扩展,我们有时称之为MySQL增强扩展,可以用于使用MySQL4.1.3或更新版本中新的高级特性。mysqli扩展在PHP
5及以后版本中包含。
mysqli扩展有一系列的优势,相对于mysql扩展的提升主要有:
1. 面向对象接口 2. prepared语句支持(即参数编译预处理,可以有效防御SQL注入的发生) 3. 多语句执行支持 4. 事务支持 5. 增强的调试能力 6. 嵌入式服务支持 7. 在提供了面向对象接口的同时也提供了一个面向过程的接口。
mysqli扩展是使用PHP扩展框架构建的,它的源代码在PHP源码目录下的ext/mysqli中
<?php $con = new mysqli("localhost", "root", "111", "php4fun_"); /* check connection */ if (mysqli_connect_errno()) { printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } $sql = "select name from users where name = ? and pass = ?"; $cmd = $con->prepare($sql); $name = $_GET[‘name‘]; $pass = $_GET[‘pass‘]; //add parameters to sql query $cmd->bind_param("ss", $name, $pass); $cmd->execute(); $cmd->bind_result($result); $cmd->fetch(); if($result) { var_dump($result); } ?>
mysqli除了可以使用参数编译预处理来进行数据库通信,同时也兼容使用面向过程的编码方式
<?php /* Connect to a MySQL server 连接数据库服务器 */ $link = mysqli_connect( ‘localhost‘, /* The host to connect to 连接MySQL地址 */ ‘root‘, /* The user to connect as 连接MySQL用户名 */ ‘111‘, /* The password to use 连接MySQL密码 */ ‘company‘); /* The default database to query 连接数据库名称*/ if (!$link) { printf("Can‘t connect to MySQL Server. Errorcode: %s ", mysqli_connect_error()); exit; } /* Send a query to the server 向服务器发送查询请求*/ if ($result = mysqli_query($link, ‘SELECT * from p8_ad_user‘)) { print("Very large cities are: "); /* Fetch the results of the query 返回查询的结果 */ while( $row = mysqli_fetch_assoc($result) ) { printf("%s (%s) ", $row[‘Name‘], $row[‘Population‘]); } /* Destroy the result set and free the memory used for it 结束查询释放内存 */ mysqli_free_result($result); } /* Close the connection 关闭连接*/ mysqli_close($link); ?>
PHP还支持很多其他的数据库连接扩展,使用方法都类似,只要遵循函数调用规范即可,更多详情请参阅
http://www.php.net/manual/zh/refs.database.php
0x2: 使用PDO抽象层与数据库通信
PDO(PHP 数据对象 PHP Database
Object),是PHP应用中的一个数据库抽象层规范。PDO提供了一个统一的API接口可以使得你的PHP应用不去关心具体要连接的数据库服务器系统
类型。也就是说,如果你使用PDO的API,可以在任何需要的时候无缝切换数据库服务器,比如从Firebird到MySQL,仅仅需要修改很少的PHP
代码。
其他数据库抽象层的例子包括Java应用中的JDBC以及Perl中的DBI。
注意: 利用 PDO 扩展自身并不能实现任何数据库功能;必须使用一个具体数据库的PDO驱动来访问数据库服务(它只是一个接口规范)
但是反过来说,一个接口提供的兼容性越强,它的定制性、特异性就相应越弱(这很容易理解),PDO接口API的主要缺点是会限制让你不能使用MySQL服务端提供所有的数据库高级特性。比如,PDO不允许使用MySQL支持的多语句执行。
在PHP5中,PDO目前已经支持大量数据库,并且在PHP6中将作为默认数据库连接方式:
1. sqlite 2. mysql 3. pgsql 4. mssql ...
PDO是基于PHP扩展框架实现的,它的源码在PHP源码目录的ext/pdo下
再次强调,PDO只是一个接口规范,它自身并不实现任何的数据库功能,程序员必须使用一个具体数据库的"PDO驱动"来访问特定的数据库
extension=php_pdo_mysql.dll
<?php $dbhost="localhost"; $dbname="company"; $dbusr="root"; $dbpwd="111"; $dbhdl=NULL; $dbstm=NULL; $opt = array(PDO::MYSQL_ATTR_INIT_COMMAND => ‘SET NAMES utf8‘,); $dsn=‘mysql:host=‘ . $dbhost . ‘;port=3306;dbname=‘ . $dbname; try { $dbhdl = new PDO($dsn, $dbusr, $dbpwd, $opt); //Display exception $dbhdl->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); } catch (PDOExceptsddttrtion $e) { //return PDOException print "Error!: " . $e->getMessage() . "<br>"; die(); } $dbstm = $dbhdl->query(‘SELECT * from p8_ad_user LIMIT 0,1‘); $rows = $dbstm->fetchAll(PDO::FETCH_ASSOC);//$rows = $dbhdl->Fetch(); print_r($rows); ?>
extension=php_pdo_pgsql.dll
<?php $host = "localhost"; $user = "root"; $pass = "111"; $db = "company"; $cursor = "cr_123456"; try { $dbh = new PDO("pgsql:host=$host;port=5432;dbname=$db;user=$user;password=$pass"); echo "Connected<p>"; } catch (Exception $e) { echo "Unable to connect: " . $e->getMessage() ."<p>"; } $dbh->beginTransaction(); $query = "SELECT * from p8_ad_user LIMIT 0,1"; $dbh->query($query); $query = "FETCH ALL IN \"$cursor\""; echo "begin data<p>"; foreach ($dbh->query($query) as $row) { echo "$row[0] $row[1] $row[2] <br>"; } echo "end data"; ?>
这里只以Mysql、PostGreSQL为例,事实上,PDO这种抽象层方式可以访问目前主流的大多数的数据库,并且PDO将成为PHP6的默认数据库连接方式,更多详情请参阅
http://www.php.net/manual/zh/book.pdo.php
0x3: 使用ODBC抽象层与数据库通信
ODBC是一种应用程序编程接口(Application Programming Interface,API),使我们有能力连接到某个数据源(比如一个MS Access 数据库)
试图通过编程语言和数据库查询访问(SQL标准化)来标准化连接方法,比如功能和配置。
ODBC的作用是充当接口或连接器,它具有双重设计目标:
1. 首先,对于ODBC 系统,它充当的是编程语言系统 2. 其次,对于数据存储系统,它充当的是 ODBC 系统。
所 以,ODBC
需要一个"对ODBC而言是编程语言"的驱动程序(例如PHP-ODBC库)和一个"对数据存储系统而言是ODBC"的驱动程序(比如
MySQL-ODBC库)。除了ODBC系统本身之外,ODBC还可以处理数据源的配置,允许数据源和编程语言之间存在模糊性。
和之前学习的扩展API接口、PDO略有不同的是,使用ODBC连接数据库要稍微麻烦一点(至少我个人这么觉得),这个"麻烦"体现在我们需要对目标数据库服务器的操作系统进行一些配置,即创建ODBC数据源,然后才可以进行ODBC连接
创建到达
MS Access 数据的 ODBC 连接的方法:
1. 在控制面板中打开管理工具 2. 双击其中的数据源 (ODBC)图标 3. 选择系统 DSN 选项卡 4. 点击系统 DSN 选项卡中的"添加"按钮 5. 选择 Microsoft Access Driver。点击完成 6. 在下一个界面,点击“选择”来定位数据库 7. 为这个数据库取一个数据源名 (DSN) 8. 点击确定
code:
<html> <body> <?php //连接一个ODBC数据源,无帐号、密码 $conn = odbc_connect(‘northwind‘, ‘‘, ‘‘); if (!$conn) { exit("Connection Failed: " . $conn); } $sql = "SELECT * FROM p8_ad_user"; $rs = odbc_exec($conn, $sql); if (!$rs) { exit("Error in SQL"); } echo "<table><tr>"; echo "<th>Companyname</th>"; echo "<th>Contactname</th></tr>"; while (odbc_fetch_row($rs)) { $username = odbc_result($rs, "username"); $password = odbc_result($rs, "password"); echo "<tr><td>$username</td>"; echo "<td>$password</td></tr>"; } odbc_close($conn); echo "</table>"; ?> </body> </html>
0x4: 使用DBX与数据库通信
PHP本身内置了DBX函数,DBX模块是一个数据库抽象层(DBX中的"X"就表示其所能支持的X种数据库)。DBX函数允许你访问所有DBX支持的数据库。
DBX支持下列数据库:
1. Mysql 2. ODBC 3. PgSQL 4. Mssql(Microsoft SQL Server) 5. Fbsql
download:
http://pecl.php.net/package/dbx http://rpmfind.net/linux/rpm2html/search.php?query=php-dbx
code:
<html> <head> <title>A PHP-DBX URL Organizer</title> <style type=text/css> p, ul, td, h1, h2, h3 { font-family: verdana, helvetica, sans-serif; } </style> </head> <body> <? /***** * TABLE DEFINITION FOR THIS EXAMPLE: * create table URLS ( * url VARCHAR(128) not null, * description TEXT, * primary key (url)); *****/ //define $MODULE as DBX_MYSQL, DBX_MSSQL, DBX_PGSQL, or your supported database $MODULE = DBX_PGSQL; $server = "localhost"; $user = "root"; $password = "111"; $database = "company"; /* FUNCTIONS */ function get_urls($dbconn, $sql) { $result = @dbx_query($dbconn, $sql); if ( $result == 0 ) { echo dbx_error($dbconn); } else { return $result; } } function url($action, $dbconn, $url, $description) { if($action == "add") { $sql = "insert into URLS values(‘$url‘, ‘$description‘)"; } elseif($action == "delete") { $url = urldecode($url); $sql = "delete from URLS where URL = ‘$url‘"; } $result = @dbx_query($dbconn, $sql); if ( $result == 0 ) { echo "<P>ERROR ADDING URL: " . dbx_error($dbconn); } else { print("<p>$action : $url succeeded!<p>"); } } /*** MAIN ***/ $dbconn = dbx_connect($MODULE, $server, $database, $user, $password) or die("CANNOT CONNECT TO DATABASE"); ?> <h1>PHP DBX URL Organizer</h1> <form action=dbx_urls.php method=post> <p><b>Add a URL:</b> <br>URL: <input type="text" name="url" maxlength="128" value="http://"> Description: <input type="text" name="description"> <input type="submit" name="addurl" value="Add URL!"> </form> <? if(isset($addurl)) { url("add", $dbconn, $url, $description); } if(isset($delete)) { url("delete", $dbconn, $delete, ""); } $sql = "select * from URLS"; $result = get_urls($dbconn, $sql); if(sizeof($result->data) == 0) { ?> <h3>Sorry, there are no URLs in the database. You should add some. <? } else { ?> <p> <table border=1 cellpadding=5 cellspacing=0 width=600> <tr><td><b>URL</b></td><td> <b>Description</b></td><td> </td></tr> <? for($i = 0; $i < sizeof($result->data); $i++) { ?> <tr><td><a href=<?=$result->data[$i][‘url‘]?>><?=$result->data[$i][‘url‘]?></a></td> <td><?=$result->data[$i][‘description‘]?></td> <td width=1><a href=dbx_urls.php?delete=<?=urlencode($result->data[$i][‘url‘])?>>delete</a></tr> <? } ?></table> <? } ?> </body> </html>
0x5: 使用DBA(Database (dbm-style) Abstraction Layer)与数据库通信
PHP的DBA抽象层是用来支持Berkeley DB这种文件型数据库的。
These functions build the foundation for accessing Berkeley DB style databases.
在柏克莱的BSD系列操作系统中,有个简单的数据库结构,它以数个文件组成超小型的数据库系统,架构成抽象层(abstraction
layer)的DBA数据库。
目前PHP支持的DBA数据库包括
1. DBM: 柏克莱发展的最早期DBA数据库 http://en.wikipedia.org/wiki/Dbm 2. NDBM: 较新且较有弹性的DBA http://en.wikipedia.org/wiki/NDBM 3. GDBM: GNU 发展的DBA ftp://ftp.gnu.org/pub/gnu/gdbm/ 4. DB2: 由Sleepycat软件开发的DB2(非IBM的DB2) http://www.openldap.org/lists/openldap-software/199905/msg00009.html 5. CDB: 这是qmail作者开发快速可靠的DBA http://pobox.com/~djb/cdb.html
安装好DBA后,使用如下代码进行连接
<?php $id = dba_open ( "/tmp/test.db" , "n" , "db2" ); if(! $id ) { echo "dba_open failedn" ; exit; } dba_replace ( "key" , "This is an example!" , $id ); if( dba_exists ( "key" , $id )) { echo dba_fetch ( "key" , $id ); dba_delete ( "key" , $id ); } dba_close ( $id ); ?>
3. 后记
以上就是PHP连接数据库的不同方式的学习,通过本文的学习,我们了解到一点
目前PHP开发中主流使用的连接数据库的技术是 1. Mysql扩展API 2. Mysqli扩展API 3. PDO抽象层
下一步希望做的事
1. 研究一下PHP和mysql进行交互的协议驱动的底层原理 2. 尝试编程简单的通信协议驱动
Copyright (c) 2014 LittleHann All rights reserved