当前位置:中国站长下载文章中心网页编程PHP编程 → 构建可配置PHP应用程序的正确方式

构建可配置PHP应用程序的正确方式

减小字体 增大字体 作者:编辑整理  来源:互联网  发布时间:2008-9-15 22:04:02
个成员变量获取值,当要设置一个成员变量时,才调用这个函数。底部的测试代码设置值并打印出新值。

下面是在命令行中运行此代码时出现的结果:

 


%phptext2.php
tempdir
foobar
%

太好了!但如何能将它存储到文件中,从而将使这个改动固定下来呢?为此,需要写文件并读取它。用于写文件的新函数,如下所示。

清单9.text3.php

 


<?php
classConfiguration
{
 ...

 functionsave()
 {
$nf='';
$fh=fopen($this->configFile,'r');
while($l=fgets($fh))
{
 if(preg_match('/^#/',$l)==false)
 {
preg_match('/^(.*?)=(.*?)$/',$l,$found);
$nf.=$found[1]."=".$this->items[$found[1]]."\n";
 }
 else
 {
$nf.=$l;
 }
}
fclose($fh);
copy($this->configFile,$this->configFile.'.bak');
$fh=fopen($this->configFile,'w');
fwrite($fh,$nf);
fclose($fh);
 }
}

$c=newConfiguration();
echo($c->TemplateDirectory."\n");
$c->TemplateDirectory='foobar';
echo($c->TemplateDirectory."\n");
$c->save();
?>

新的save函数巧妙地操作config.txt。我并没有仅用更新过的配置项重写文件(这样会移除掉注释),而是读取了这个文件并灵活地重写了$items数组中的内容。这样的话,就保留了文件中的注释。

在命令行运行该脚本并输出文本配置文件中的内容,能够看到下列输出。

清单10.保存函数输出

 


%phptext3.php
tempdir
foobar
%catconfig.txt
#Myapplication'sconfigurationfile
Title=MyApp
TemplateDirectory=foobar
%

原始的config.txt文件现在被新值更新了。

XML配置文件

尽管文本文件易于阅读及编辑,但却不如XML文件流行。另外,XML有众多适用的编辑器,这些编辑器能够理解标记、特殊符号转义等等。所以配置文件的XML版本会是什么样的呢?清单11显示了XML格式的配置文件。

清单11.config.xml

 


<?xmlversion="1.0"?>
<config>
<Title>MyApp</Title>
<TemplateDirectory>tempdir</TemplateDirectory>
</config>

清单12显示了使用XML来装载配置设置的Configuration类的更新版。

清单12.xml1.php

 


<?php
classConfiguration
{
 private$configFile='config.xml';
 private$items=array();
 function__construct(){$this->parse();}
 function__get($id){return$this->items[$id];}
 functionparse()
 {
$doc=newDOMDocument();
$doc->load($this->configFile);
$cn=$doc->getElementsByTagName("config");
$nodes=$cn->item(0)->getElementsByTagName("*");
foreach($nodesas$node)
$this->items[$node->nodeName]=$node->nodeValue;
 } 
}

$c=newConfiguration();
echo($c->TemplateDirectory."\n");
?>

看起来XML还有另一个好处:代码比文本版的代码更为简洁、容易。为保存这个XML,需要另一个版本的save函数,将结果保存为XML格式,而不是文本格式。

清单13.xml2.php

 


...
functionsave()
{
 $doc=newDOMDocument();
 $doc->formatOutput=true;

 $r=$doc->createElement("config");
 $doc->appendChild($r);

 foreach($this->itemsas$k=>$v)
 {
$kn=$doc->createElement($k);
$kn->appendChild($doc->createTextNode($v));
$r->appendChild($kn);
 }

 copy($this->configFile,$this->configFile.'.bak');

 $doc->save($this->configFile);
}
...

这段代码创建了一个新的XML文档对象模型(DocumentObjectModel,DOM),然后将$items数组中的所有数据都保存到这个模型中。完成这些以后,使用save方法将XML保存为一个文件。

使用数据库

最后的替代方式是使用一个数据库保存配置元素的值。那首先要用一个简单的模式来存储配置数据。下面是一个简单的模式。

清单14.schema.sql

 


DROPTABLEIFEXISTSsettings;
CREATETABLEsettings(
 idMEDIUMINTNOTNULLAUTO_INCREMENT,
 nameTEXT,
 valueTEXT,
 PRIMARYKEY(id)
);

这要求进行一些基于应用程序需求的调整。例如,如果想让配置元素按照每个用户进行存储,就需要添加用户ID作为额外的一列。

为了读取及写入数据,我编写了如图15所示的更新过的Configuration类。

清单15.db1.php

 


<?php
require_once('DB.php');
$dsn='mysql://root:password@localhost/config';
$db=&DB::Connect($dsn,array());
if(PEAR::isError($db)){die($db->getMessage());}

classConfiguration
{
 private$configFile='config.xml';
 private$items=array();
 function__construct(){$this->parse();}
 function__get($id){return$this->items[$id];}
 function__set($id,$v)
 {
global$db;
$this->items[$id]=$v;
$sth1=$db->prepare('DELETEFROMsettingsWHEREname=?');
$db->execute($sth1,$id);
if(PEAR::isError($db)){die($db->getMessage());}
$sth2=$db->prepare('INSERTINTOsettings(id,name,value)VALUES(0,?,?)');
$db->execute($sth2,array($id,$v));
if(PEAR::isError($db)){die($db->getMessage());}
 }

 functionparse()
 {
global$db;
$doc=newDOMDocument();
$doc->load($this->configFile);
$cn=$doc->getElementsByTagName("config");
$nodes=$cn->item(0)->getElementsByTagName("*");
foreach($nodesas$node)
$this->items[$node->nodeName]=$node->nodeValue;
$res=$db->query('SELECTname,valueFROMsettings');
if(PEAR::isError($db)){die($db->getMessage());}
while($res->fetchInto($row)){
 $this->items[$row[0]]=$row[1];
}
 }
}

$c=newConfiguration();
echo($c->TemplateDirectory."\n");
$c->TemplateDirectory='newfoo';
echo($c->TemplateDirectory."\n");
?>

这实际上是一个混合的文本/数据库解决方案。请仔细观察parse方法。该类首先读取文本文件来获取初始值,然后读取数据库,进而将键更新为最新的值。在设置一个值后,键就从数据库中移除掉,并添加一条具有更新过的值的新记录。

观察Configuration类如何通过本文的多个版本来发挥作用是一件有趣的事,该类能从文本文件、XML及数据库中读取数据,并一直保持相同的接口。我鼓励您在开发中也使用具有相同稳定性的接口。对于对象的客户机来说,这项工作具体是如何运行的是不

上一页  [1] [2] [3]  下一页