首页 > 开发 > PHP > 正文

PHPLIB访问多个数据库

2024-05-04 22:58:48
字体:
来源:转载
供稿:网友

【摘 要】 如果你要使用多个数据库的话,它就显得力不从心了,本文介绍了通过扩展phplib,让你鱼和熊掌兼得,在使用phplib的同时可以使用多个数据库,而且从中你也可以了解到面向对象编程和如何扩展库的知识。
  phplib是php的一些扩展库,使用它我们可以很方便地对数据库进行各种操作,不过,如果你要使用多个数据库的话,它就显得力不从心了,本文介绍了通过扩展phplib,让你鱼和熊掌兼得,在使用phplib的同时可以使用多个数据库,而且从中你也可以了解到面向对象编程和如何扩展库的知识,值得一读。

数据库管理

   你可以在一个大型的数据库中放入任何表。不过时间长了,将会令数据库变得越来越大,服务器可能会跟不上io的工作,或者没有足够的内存应付所有的访问?要分开现有的数据又非常难。明智的办法是开始时就使用分开的数据库,并且进行有效的数据库管理。 如果你有一个卖书的网站,你可能有作者的列表,书价的列表,还有当前的库存和订单的列表。当你的业务不断增长时,订单将会不断地增长,而且处理每个订单都需要进行很多的磁盘访问。很可能你将在某一天将所有的订单都放到一个会计系统中。

  现在就将订单放到一个独立的数据库吧。由于库存也是通过订单更新的,因此库存量也放到同样的数据库中。

  作者的列表和书的列表都是一些静态的信息,要经常读取,但很少更新。实际上,更新一个作者的记录可能只需要每5年一次,只在作者写了一本新书(或者去世)时进行。放这些数据的服务器的配置可与放订单数据库的服务器完全不同。

包含phplib

  phplib通过一个称为db_sql的类访问sql数据库。根据你需要使用的数据库类型,将不同的inc文件包含在你的代码中。在这个例子中,我使用mysql的版本。

  为了在你的代码中使用db_sql,要将phplib文件安装在它们自己的目录中。然后,找到你的cgi-bin目录,并且在cgi-bin的目录旁创建phplib目录。下一步,拷贝所有的phplib .inc文件到phplib目录。最后,修改php.inc文件,只要将“include_path=”的行改为该phplib目录就可以了。

include_path是php使用include()或者require()时查找的目录,在我的nt workstation中,include的路径是:

include_path = ".;i:/project52/includes;i:/project52/phplib";

在linux的系统上

include_path = ".;/home/httpd/includes;/home/httpd/phplib";

在每个php页面的顶部加入
<?php

require(common.php);

?>
common.php3放在includes目录中,包含了每个页面要用到的所有数据和函数。在这个例子中的common.php是:
<?php

require(db_mysql.inc);
require(ct_sql.inc);
require(session.inc);
require(auth.inc);
require(perm.inc);
require(user.inc);
require(page.inc);

?>

  如果你想知道每个inc文件的用处,可阅读http://phplib.netuse.de上的phplib文档。db_mysql.inc包含了所有db_sql类的定义。如果你想使用postgresql代替mysql,只要用db_pgsql.inc代替db_mysql.inc就可以了。还有10个其它的.inc文件,可以使用ms sql、oracle、sybase或者其它的数据库。

  要注意的是,在这个例子中,require()和include()是完全一样的。不过,如果放在代码中,或者在if语句中使用时,require()和include的使用是完全不同的,并且有不同的运行结果。

扩展phplib

  phplib通过一个db_sql类产生的对象来访问数据库。db_mysql.inc包含了为mysql修改过的db_sql类。我们将通过在common.php中加入代码来扩展db_sql,这些代码将加在包含db_mysql.inc的行后。

db_sql包含了很多用作查询的函数,我们要作修改的是:

<?php

/* public: 连接管理 */
function connect($database = "", $host = "", $user = "", $password = "") {
/* 处理默认连接 */
if ("" == $database)
$database = $this->database;
if ("" == $host)
$host = $this->host;
if ("" == $user)
$user = $this->user;
if ("" == $password)
$password = $this->password;

/* 建立连接,选择数据库 */

if ( 0 == $this->link_id ) {
$this->link_id=mysql_pconnect($host, $user, $password);
if (!$this->link_id) {
$this->halt("pconnect($host, $user, /$password) failed.");
return 0;
}

if ([email protected]_select_db($database,$this->link_id)) {
$this->halt("cannot use database ".$this->database);
return 0;
}
}

return $this->link_id;
}

?>

  在你的db_mysql.inc(或者其它数据库的相关.inc文件)中找到connect()函数,然后将它拷贝到common.php,放到包含db_mysql.inc代码的后面,在后面,还要将它封装为一个类的定义。

我发现这些代码有些难读,因此,首先令拷贝来的代码的可读性更好:

<?php

/* public: 连接管理*/

function connect($database = "", $host = "", $user = "", $password = "") {
/* 处理默认连接 */
if ("" == $database) {
$database = $this->database;
}
if ("" == $host) {
$host = $this->host;
}
if ("" == $user) {
$user = $this->user;
}
if ("" == $password) {
$password = $this->password;
}
/* 建立连接,选择数据库 */
if ( 0 == $this->link_id ) {
$this->link_id=mysql_pconnect($host, $user, $password);
if (!$this->link_id) {
$this->halt("pconnect($host, $user, /$password) failed.");
return 0;
}
if ([email protected]_select_db($database,$this->link_id)) {
$this->halt("cannot use database ".$this->database);
return 0;
}
}
return $this->link_id;
}

?>

  我调整了一下括号的位置,并且在单行的前后也加入了一个大括号。在php的if语句中,如果只有一句代码的话你可以不用括号,但是,如果你增加多一行代码,就会马上出错。因此我建议你加入一个括号,以免后来加入代码时出错。

  在改变connect的代码之前,先要了解一下connect()是如何工作的,它检查当前是否存在一个连接,如果不存在连接的话,就创建一个连接。在每次的数据库查询之前,首先运行这个connect()函数。可惜的是,它只在首次连接的时候选择数据库,如果你的php页面使用超过一个数据库,connect()并不会选择另外的数据库。

  要改变代码的话,有几种不同的方法。我们要选择一种对phplib的影响最小,而且可让我们在需要分析问题的时候,能够显示数据库连接状态的方法。我们需要在phplib外保存连接id和数据库的名字。只要在common.php加入:

<?php

$db_connection = 0; // 数据库连接的id
$db_database = ""; // 当前数据库的状态

?>

  下一步,我们要对phplib作修改,以便在这些变量中存储连接id和数据库的名字。在其它的代码中,你可以设置和使用同样的变量名。在分析问题时,如果你需要知道现在使用哪个数据库,只要在页面中插入以下的代码:

<?php

print("

db_database: " . $db_database . "

");

?>

我们怎样才能让connect()使用这些新变量呢?我们可以在顶部加入一行:

<?php

{
globals $db_connect, $db_database;
/* handle defaults */

?>

通过这些代码,新变量就可被connect()访问到

在定义了$db_database后,加入:
<?php

function db_connect($db_connect_host="", $db_connect_user="",$db_connect_pass="") {
globals $db_connect;
if(!empty($db_connect_host)) {
$db_connect = mysql_pconnect($db_connect_host,
$db_connect_user, $db_connect_pass);
}
return($db_connect);
}

function db_database($db_database_new="") {
globals $db_database;
if(!empty($db_database_new)) {
$db_database = @mysql_select_db($db_database_new, db_connect());
}
return($db_database);
}

?>

  只要定义这些公共的函数一次,你就可以在不同的地方使用这些公共的变量,而不需要加入global申明。以下就是使用上面db函数的公共函数:

<?php

function connect($database = "", $host = "", $user = "", $password = "") {
/* 处理默认连接 */
if ("" == $database) {
$database = $this->database;
}
if ("" == $host) {
$host = $this->host;
}
if ("" == $user) {
$user = $this->user;
}
if ("" == $password) {
$password = $this->password;
}
/* 建立连接,选择数据库 */
if ( 0 == db_connect()) {
$this->link_id = db_connect($host, $user, $password);
if (!$this->link_id) {
$this->halt("pconnect($host, $user, /$password) failed.");
return 0;
}
}
if (0 != db_connect()) {
if($database != db_database()) {
$this->database = db_database($database))
if(empty($this->database)) {
$this->halt("cannot use database " . $this->database);
return 0;
}
}
}
return $this->link_id;
}

?>

留意以下改变:

  对数据库的测试从连接的测试中分离出来,这样即使connect()有一个当前连接时,还可以检查是否要换成另外的数据库。这意味着与以前相比,db_connect()和0作比较的次数多了一倍,不过这个额外的处理是必要的。

  我们将数据库连接和数据库选择放在phplib外,这样你就可以在php代码的任何地方使用同样的数据库选择函数。

  不过,现在的处理有一个限制,这里我们是假定对于所有的数据库,都使用同样的主机、用户和密码。如果你的数据库对于不同的用户有不同的权限,你必须建立一个特别的连接来访问它。怎样做?只要定义以下变量就可以了:

<?php

$db_host = "";
$db_user = "";
$db_pass = "";

?>

  通过扩展db_database()函数,将当前的用户和主机和某个用户和主机作对比就行。你还可以加入:

<?php

$db_type = "";

?>

  这个变量用来存储数据库的类型,mysql或者oracle等。这样你就可以访问多个数据库。

  不过要改变代码来处理多个不同类型的数据库是颇复杂的。你必须还要改变查询函数,以及连接和选择函数。你或许可通过php的odbc来连接,然后使用phplib的odbc选项来处理。odbc通过一个通用的方式来处理多种数据库,因此将会慢一点。odbc虽然可让你使用同样的代码来处理多个不同类型的数据库。但是在需要用到不同处理格式的日期时,将会有问题,而且在数据库间也会存在一些奇怪的差异。odbc只是简化了连接,但是并没有修改数据库解释数据和sql的方式。

  现在来学习一下如何重新定义一个对象类。connect()函数被封装到一个类的定义中:
<?php

class db_sql {

}

?>

我们将该函数拷贝到common.php时,我们必须重新定义db_sql类,我们可以这样封装connect():
<?php

class db_db_sql extends db_sql {

}

?>

  要详细了解"extends"的工作,我们可以看看php文档中关于对象和类的部分。简单说来:扩展部分的任何定义替换和覆盖了以前的所有定义。

现在可以使用db_db_sql。在你配置phplib时,你要做以下声明:

<?php

$x = new db_sql;

?> change it to: <?php

$x = new db_db_sql;

?>

这样你就可以使用修改的类,而不是以前的类。

  在连接数据库出错的时候,你可以在外部的函数中输出目前的连接状态。如果sql语句出错,你也可以将db_sql中的query()函数拷贝到common.php的db_db_sql中,然后插入一个输出语句,看看当前的sql语句是什么。

你也可以将错误或者诊断的信息写到一个磁盘文件中。通过定义

$db_log_file = "t:/diag.txt";

或者一个类似的文本文件。如果使用windows,你要确保该目录存在,否则你会得到一个错误的信息。

然后定义一个函数:

<?php

function db_log($db_log_message) {
globals $db_log_file;
$db_log_f = fopen($db_log_file, "a");
fwrite($db_log_f, date("y m d h:i:s")." ".$db_log_message."/r/n");
fclose($db_log_f);
}

?>

在你需要记录信息的地方,加入以下代码:

<?php

db_log("current database: " . db_database());

?>

  其实你可以使用内置的或者系统的日志文件。不过这样你就要在一大堆的文件中查找一小段信息。因此这个独立的记录文件可帮助你进行测试。我建议在记录前后写以下的代码:

<?php

db_log("current database: " . db_database());
db_database("bookcatalogue");
db_log("current database: " . db_database());

?>

  在数据访问时,要记得使用正确的数据库,而不是phplib中定义的数据库。你可以为该数据库创建一个封装的函数,或者改变你使用的函数。如果你使用mysql_query(),你可以先用db_database(),你可以用

<?php

$result = mysql_db_query(db_database("bookcatalogue"), "select * from?",
db_connect());

?> which suggests the function: <?php

function db_query($db_query_database, $db_query_sql) {
return(mysql_db_query(db_database($db_query_database), $db_query_sql,
db_connect());
}

?>

来代替

<?php

db_database("bookcatalogue");
$result = mysql_query("select * from?", db_connect());

?>

现在你可以做到

.使用phplib(或者类似的软件)来访问多个数据库
.扩展类/对象
.插入诊断检查
.建立日志文件

  通过这篇文章,相信对于如何扩展一个类,你也有了一些概念,自己实践一下吧。



发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表