第六章:数据库连接程序库
1.开始
为什么使用数据库连接程序库
使用该库可以使php使用不同种类的数据库,利用该库的函数可以在不同种类的数据库间切换。
2.库的介绍
代表性的数据库连接程序库是Pear DB。ADOdb比Pear DB功能更高,它具有开发query功能和缓存功能,它还有很多便于获得数据的函数。缓存功能主要针对数据负荷过大的情况。
中有一种实现O/R映射的数据库连接程序库Pear DB_DataObject。O/R映射是指将对象和数据库关联的方法。比如说对对象$table->name的操作既是对该对象代表的数据库的操作。
另外SQL Relay也很重要,它可以建立一定数量的连接病任意使用他们,该技术叫连接池。但由于连接的数量不能控制,容易出现数据负荷过大的情况。
3.安装ADOdb
从http://adodb.sourceforge.net/下载ADOOdb,解压后置于/mojavi/opt/adodb。如果用require_once()读入放在哪里都没问题。
4.怎样使用ADOdb
首先是数据库连接程序库的读入和缓存文件的设定。
/*
* 读入ADOdb类
*/
include('/path/to/adodb.inc.php');
/*
* 设定ADOdb
* 设定缓存文件地址和有效时间。
* 在用全局变量设定时,在被include调用的文件以外的其他文件内设定时,需要通过$GLOBALS[]设定。
*/
$ADODB_CACHE_DIR = $cachedir;
/*
可将任意地址的缓存文件的地址值赋给$cachedir。(需要写入权限)。
$ADODB_CACHE_DIR以外其他地方取得数据的方法通过$ADODB_FETCH_MODE等设定。
下面是连接数据库
* 连接数据库
*/
$DB = NewADOConnection($sqltype);
$DB->Connect($server, $user, $password, $dbname);
$sqltype数据库种类。
$server服务器地址。
$user,$password用户名密码。
$dbname数据库名。
通过对ADOConnection类变量$DB进行各种操作。
准备了如下三种方法,使你通过select获得数据。
/*
* 取得数据的方法1
* 通过指针获得
*/
$sql = "SELECT * FROM test_table";
$rs = $DB->Execute($sql); //将结果赋值给$rs
while (!$rs->EOF) { //反复移动指针直到最后一条记录
print_r($rs->fields); //打印指针指定的纪录
$rs->MoveNext(); //指针移到下一条纪录
}
/*
* 取得数据的方法2
* 通过PEAR style获得
*/
$rs = $DB->Execute($sql); //将结果赋值给$rs
while ($array = $rs->FetchRow()) { //取出的记录传给数组,指针移到下一条纪录
print_r($array); //打印数组
}
这两个方法,都是通过执行$DB->Execute得到ResultSet类变量$rs,然后从$rs中得到一条记录。得到的数组,通过$ADODB_FETCH_MODE,既可用下标访问($array[0]),也可用字段名访问($array['col1'])。默认情况下,不同的数据库产品的操作不同。
/*
* 取得数据的方法3
* 在SQL执行同时就获得数据的方法
*/
$val = $DB->GetOne($sql); //获得第一条记录的第一个字段
$row = $DB->GetRow($sql); //获得第一条记录
$arr = $DB->GetAll($sql); //获得所有数据
最后是INSERT和UPDATE之类的操作。
/*
* 插入纪录
*/
$sql = "INSERT into test_table (col1,col2) VALUES (111,222)";
$ok = $DB->Execute($sql); //出错时$ok = false
5.数据库设定
下面对Mochat程序进行改良。使用环境入下:
PostgreSQL Ver8(以前版本也可以)
连接到服务器 localhost
端口 5432
数据库名 mochat
编码 euc-jp
用户名 mochat
密码 mochacha
做成表
CREATE TABLE t_comment (
pid serial PRIMARY KEY,
name text,
comment text,
regist timestamp default CURRENT_TIMESTAMP,
valid boolean DEFAULT true
);
pid,regist,valid的默认值自动设定。
以上内容在/webapp/config.php设定
/**
* ADOdb Settiong
*/
define('ADODB_DIR', OPT_DIR . 'adodb/');
define('ADODB_CACHE_DIR' , BASE_DIR . 'adodb');
define('ADODB_CACHE_SECS' , '60');
define('ADODB_DEBUG' , false);
define('SQL_TYPE' , 'postgres');
define('SQL_SERVER', 'localhost:5432');
define('SQL_USER', 'mochat');
define('SQL_PASSWORD', 'mochacha');
define('SQL_DATABASE', 'mochat');
变量名 功能 设定值
ADODB_DIR ADOdb 配置文件的地址 /mojavi/opt/adodb/
ADODB_CACHE_DIR 缓存文件的地址 /webapp/adodb/
ADODB_CACHE_SECS 缓存有效时间 60秒
ADODB_DEBUG ADOdb 是否使用库调试功能 不使用
SQL_TYPE 数据库种类 PostgreSQL
SQL_SERVER 连接到的主机 localhost:5432
SQL_USER 用户名 mochat
SQL_PASSWORD 密码 mochacha
SQL_DATABASE 数据库名 mochat
6.做成DBAction类
开发调用并设定ADOdb的类。
在Mojavi的Action类中定义initialize函数。
function initialize (&$controller, &$request, &$user)
{
return TRUE;
}
Action类执行时initialize函数最先执行。initialize函数返回true时继续处理,返回false时停止处理。
类DBAction继承类Action,他具有用于连接数据库的initialize函数。
webapp/lib/DBAction.class.php
<?php
require_once(ADODB_DIR . 'adodb.inc.php');
class DBAction extends Action
{
function initialize (&$controller, &$request, &$user)
{
if (!$request->hasAttribute('initialized'))
{
//ADOdbの?定
$GLOBALS["ADODB_CACHE_DIR"] = ADODB_CACHE_DIR;
$DB = NewADOConnection(SQL_TYPE);
$DB->debug = ADODB_DEBUG; //是否使用库调试功能
$DB->cacheSecs = ADODB_CACHE_SECS; //缓存有效时间
//接?
$ok = $DB->Connect(SQL_SERVER, SQL_USER , SQL_PASSWORD, SQL_DATABASE);
if(!$ok) {
//错误处理
print '不能连接数据库。';
return FALSE;
}
//将连接保存在request
$request->setAttribute('DB',$DB);
//防止作相同处理的标记
$request->setAttribute('initialized', TRUE);
}
return TRUE;
}
}
?>
继承者各类的Action,在初始化时已自动连接到数据库,并将连接存入Request。
下面是例子。
<?php
require_once(LIB_DIR . 'DBAction.class.php');
class DBTestAction extends DBAction{
function Execute(&$controller, &$request, &$user){
$DB = $request->getAttribute('DB');
$sql = "SELECT * FROM t_comment";
$array = $DB->CacheGetAll($sql);
print_r($array);
return VIEW_NONE;
}
}
?>
php将自动断开与数据库的连接。不用写出代码。
7.使用数据库
我们将改良Mochat,使它在发言时记录下id和发言时间
首先,修改/webapp/modules/Mochat/actions/IndexAction.class.php的 getDefaultView(通常用来显示发言)。
/*
* GET时:取得数据
*/
function getDefaultView (&$controller, &$request, &$user)
{
$DB = $request->getAttribute('DB');
//取得数据
$sql = "SELECT pid,name,comment,regist FROM t_comment";
$where = "WHERE valid = true";
$order = "ORDER BY regist DESC";
$limit = "LIMIT 10";
$data = $DB->GetAll("$sql $where $order $limit");
//在属性中设置数据
$request->setAttribute('data', $data);
//继承姓名
$request->setAttribute('name',$request->getParameter('name'));
return VIEW_INPUT;
}
$limit = "LIMIT 10";表示限制发言数。在这里直接设成10。但最好在config.php之类的文件中设定。
修改Execute函数
/*
* POST时:插入数据
*/
function Execute (&$controller, &$request, &$user)
{
if($request->getParameter('comment')){
$DB = $request->getAttribute('DB');
//得到要插入的数据
$name = $DB->qstr($request->getParameter('name'));
$comment = $DB->qstr($request->getParameter('comment'));
//保存数据
$sql = "INSERT INTO t_comment(name,comment) VALUES ($name,$comment)";
$DB->Execute($sql);
}
//传送给自身
$module = $controller->getRequestModule(); //模块名
$name = urlencode($request->getParameter('name')); //姓名
$controller->redirect("?module=$module&name=$name");
}
修改/webapp/modules/Mochat/views/IndexView_input.class.php
<?php
require_once(LIB_DIR . 'CustomSmartyRenderer.class.php');
class IndexView extends View
{
function & execute (&$controller, &$request, &$user)
{
$renderer =& new CustomSmartyRenderer($controller, $request, $user, true, 60);
//指定模板
$renderer->setTemplate('mochat_input.tpl');
//将数据写入模板
$renderer->setAttribute('data', $request->getAttribute('data'));
$renderer->setAttribute('errors', $request->getErrors());
$renderer->setAttribute('name', $request->getAttribute('name'));
return $renderer;
}
}
?>
修改/webapp/modules/Mochat/templates/mochat_input.class.php
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
<title>Mochat - 聊天</title>
</head>
<body>
<form method="POST" action="./?module=Mochat">
姓名:<input type=text name="name" value="{$name|escape}">
发言:<input type=text name="comment" size=50>
<input type=submit value="发言">
</form>
{foreach from=$errors item=error}{$error}<BR>{/foreach}
{foreach from=$data item=cur_dat}
<HR>{$cur_dat.name}:{$cur_dat.comment}
{/foreach}
<HR>
</body>
</html>
8.ADOdb的缓存功能
在原函数名前加上Cache(如Execute()时为CacheExecute())生成的函数就可以使用ADOdb的缓存功能。请求缓存时用到$DB->CacheFlush()函数,$DB->CacheFlush()中无参数,获得所有缓存。以sql语句为参数,则获得相适合的参数。
在Mochat中使用缓存功能时,GET方式下使用CacheGetAll(),POST方式下INSERT后使用CacheFlush()的话,显示速度显著改善。