关于奇矩互动奇矩互动招贤纳士奇矩互动优质虚拟主机Discuz!商业用户享有本站VIP服务LAMP环境配置手册(CentOS5.1)
 11 12
发新话题
打印

PHP学习专题--第20期:PEAR应用篇

本主题由 aming 于 2008-7-1 08:58 设置高亮

PHP学习专题--第20期:PEAR应用篇

PEAR是一种代码库,它为标准程序功能提供预先编写的类,从而大大降低了应用程序的开发时间。PEAR在概念上类同于Perl的CPAN,PEAR包含了具有丰富特性的功能函数,包括数据库、邮件和错误处理等。

用Pear加速PHP程序开发

及时交付应用程序是确定解决方案采用何种技术的关键所在,PHP借助于PEAR(PHP Extension and Application Repository:PHP扩展与应用库)会大大促进其开发过程。PEAR是一种代码库,它为标准程序功能提供预先编写的类,从而大大降低了应用程序的开发时间。PEAR在概念上类同于Perl的CPAN,PEAR包含了具有丰富特性的功能函数,包括数据库、邮件和错误处理等。在采用PEAR的情况下,开发人员就可以部署和增强已经编写的基本函数同时把注意力集中到编写程序新功能这一方面上来。
PEAR基础

创建PEAR的目的是为开发人员共享PHP代码和促进代码的重用提供一种标准化的方式。该项目始终处于开发的过程中,用户可以提交自己编写的代码供加入PEAR库使用,后者则同PHP捆绑。所有的PEAR包都在考虑到语法和可读性的情况下严格遵守编码规则,这些代码由用C语言编写的PHP或者PHP扩展所组成。

Stig Bakken于1999年晚些时候开始着手开发PEAR项目。他的目的是创建一个有组织的代码库,由这个代码库起到PHP开发人员团体的资源库作用。该项目在过去的两年里成长的非常快,目前已经包含了相当多的、非常有用的可重用代码。虽然其他的PHP代码库也不少,比如Zend的Code GalleryPHP Builder的Source Code Snippet Library等等都非常有名,但是,PEAR提供了一种便利函数之间互操作的标准。此外,提交给PEAR的代码会接受严格的检查,由这类标准和检查措施保证代码的质量和可靠性。


有用的网站



可用的功能PEAR分成三类:PEAR核心组件、PEAR包和PECL包。核心组件(Core Component)包括PEAR和PEAR_Error的基类以及数据库、HTTP、日志记录和电子邮件函数等。PEAR包包括提供认证、联网和文件系统特性的函数以及采用XML和HTML模版的工具等。PECL包是对PHP的扩展,它用C语言编写,并不遵守编码规则。目前,所有这一类的代码都是实验性的。要了解有关PEAR功能的更多信息请参考PEAR在线手册

假如你有兴趣给PEAR提交代码,你可以加入PEAR开发者邮件列表并且请求大家检查你的代码,从而实现以上目的。不过,你得注意到已经包括在库内的函数并且遵守PEAR的编码规则。
从哪里获取PEAR

PEAR捆绑在PHP发布包内,当你安装PHP的时候也就同时安装了PEAR。假如你打算获得一个稳定的版本,而且你可以在没有最新PEAR版本的情况下也活得下去,那么你可以从php.net的下载网页获得最新的PHP版本。假如你喜爱冒险,希望采用最新版本的PEAR,你可以按照匿名CVS访问的指示用CVS客户程序下载它。

安装了PHP之后PEAR资源就会被放置到~/php/PEAR/ 目录下。你不妨把自己的php目录位置增加到php.ini的include_path参数中来(比如:include_path = ".:/usr/local/lib/php";),这样就可以使用PEAR功能了。
如何使用PEAR现在所要做的无非是在用到函数和你编写的其他类的地方采用require_once()。清单A中的例子使用了PEAR的电子邮件特性Sendmail。这部分代码例示了PEAR库内的Mail.php文件,该文件是对PEAR.php类的扩展。

接下来,我们设置一些必要的变量,它们是$recipients、$headers和$body,这些变量是所有PEAR Mail函数和$params所需要的。你可以参在线PEAR手册找出这些变量的设置方法。在PEAR代码本身的注释中也蕴涵了很多信息,不过一般而言,网站对你的帮助还是最大的。

最后,示例代码会调用PEAR Mail类。首先,我们用~/php/Mail.php文件中的Mail::factory方法为邮件驱动程序包含适当的类文件,在我们所举的例子里就是Sendmail(位于~/php/Mail/sendmail.php文件内)。接着,我们从PEAR Mail类里实际调用邮件发送函数。当我们对Mail类实例化的时候采用引用(=&)就可以通过引用名$mail_object引用该类了。

假如你想了解PEAR DB函数的用法,你不妨到 Quick Start Guide to Pear DB去看看,它是由Tomas V. V. Cox负责维护的。

为什么使用PEAR如上所述,PEAR功能部署简单,同时不需要额外的编程。虽然我们可以用PHP的固有函数达到同样的结果,但是,部署PEAR模块可以立即为我们带来错误检查等实际利益,同时还便利了程序的重用。

此外,越来越多的高级应用程序也开始采用PEAR了,而PEAR的代码库也在不断的增长之中。因为PEAR包含在PHP许可权之内,所以你可以免费使用或者修改你选择的函数。还有,你再也不必反复编写令人麻木的认证模块了,这对开发人员来说可是一项具有相当吸引力的好处,而且你还可以享受到定制开发的莫大优点。

好处多多采用合格的预编写、可重用代码,你就可以显著地加快应用程序的开发周期而不必在技术选择上过分地费脑筋了。PEAR是PHP团体为便利开发者而付出的努力所结出的硕果,它提供了实现优秀应用程序的一整套方法。采用PEAR代码以及为其做出自己的贡献不仅加快了项目交付时间,同时还可以在今天和未来开发出质量更好的应用程序。
TechRepublic是一个专为各类IT专业人士设立的在线社区以及资源中心,我们提供有深度的技术文章,这些文章由IT专家写成,面对IT专家读者。除了提供从Windows到e-mail到防火墙等各种文章以外,我们还提供IT业界分析,下载,管理要点,讨论组以及新闻邮件服务。

TOP

PEAR应用之AUTH_HTTP

使用AUTH_HTTP,可以方便地构建基于HTTP验证的程序,而且可以自由地指定用户数据表,操作简单易用...
例子:
复制内容到剪贴板
代码:
<?php
require_once("Auth/HTTP.php");
$options = array(
'dsn'=>"mysql://root:@localhost/test", //数据库连接字串
'table'=>"test_http",                  //用户表
'usernamecol'=>"name",            // 用户名字段
'passwordcol'=>"passwd",            //用户密码字段
'cryptType'=>"md5",                // 密码加密码方式
'db_fields'=>"*",                  
);
$a = new Auth_HTTP("DB", $options);

$a->setRealm('yourrealm');            // realm name
$a->setCancelText('Error 401');        // 验证失败时的提示信息
$a->start();                    // starting the authentication process

if($a->getAuth())                // 成功
{
    echo "Hello $a->username welcome to my secret page";
  echo $a->getAuthData('userid');        // 获得其它字段
  echo $a->getAuthData('telephone');      //  
  echo $a->getAuthData('email');  

//print_r($a);
};
?>
在要验证的程序前加上此程序即可..

TOP

Pear :: Pager分页类简介

Pear的Pager分页类是一个很好用的php分页类,扩展性很强,能够适应各种分页情况的需求,至少我在几年间大大小小的项目里,基本上没有为分页额外写过代码,全部都是用的Pager,足见Pager的可用性之强.下面用代码来看看它的使用范例:

例子1
PLAIN TEXT
PHP:
复制内容到剪贴板
代码:
<?php
require_once 'Pager/Pager.php';
$params = array(
    'mode'       => 'Jumping',
    'perPage'    => 3,
    'delta'      => 2,
    'itemData'   => array('a','b','c','d','e',[...omissis...],'z')
);
$pager = & Pager::factory($params);
$data  = $pager->getPageData();
$links = $pager->getLinks();
//$links is an ordered+associative array with 'back'/'pages'/'next'/'first'/'last'/'all' links
//NB: $links['all'] is the same as $pager->links;

//echo links to other pages:
echo $links['all'];

//Pager can also generate <link rel="first|prev|next|last"> tags
echo $pager->linkTags;

//Show data for current page:
echo 'PAGED DATA: ' ; print_r($data);

//Results from methods:
echo 'getCurrentPageID()...: '; var_dump($pager->getCurrentPageID());
echo 'getNextPageID()......: '; var_dump($pager->getNextPageID());
echo 'getPreviousPageID()..: '; var_dump($pager->getPreviousPageID());
echo 'numItems()...........: '; var_dump($pager->numItems());
echo 'numPages()...........: '; var_dump($pager->numPages());
echo 'isFirstPage()........: '; var_dump($pager->isFirstPage());
echo 'isLastPage().........: '; var_dump($pager->isLastPage());
echo 'isLastPageComplete().: '; var_dump($pager->isLastPageComplete());
echo '$pager->range........: '; var_dump($pager->range);
?>
Pager的使用,只要调整$param数组的参数,就可以应付很多种分页情况了.代码中的$links数组包含了一些链接,如上一页/页码/下一页/第一页/末页/全部.

例2
如今许多网站为了SEO,把动态页使用rewrite规则伪造成静态页的形式,例如下面这个.htaccess配置:

RewriteEngine on
#Options FollowSymlinks

RewriteBase /
RewriteRule ^articles/([a-z]{1,12})/art([0-9]{1,4})\.html$ /article.php?num=$2&month=$1 [L]

即使在这种情况下,Pager分页仍然有办法工作,见下面的code

PLAIN TEXT
PHP:
复制内容到剪贴板
代码:
<?php
require_once 'Pager/Pager.php';

//first pager
$params1 = array(
    'perPage'    => 3,
    'urlVar'     => pageID_articles,  //1st identifier
    'itemData'   => $someArray
);
$pager1 = & Pager::factory($params1);
$data1  = $pager1->getPageData();
$links1 = $pager1->getLinks();

//second pager
$params2 = array(
    'perPage'    => 8,
    'urlVar'     => pageID_news,      //2nd identifier
    'itemData'   => $someOtherArray
);
$pager2 = & Pager::factory($params2);
$data2  = $pager2->getPageData();
$links2 = $pager2->getLinks();
?>
通过配置$param,就能够把链接 "/articles/march/art15.html"对应到链接"/article.php?num=15&month=march" ,比较灵活的表现

扩展性
Pager类的扩展性,平心而论,也是不错的.比如以前写的path方式的分页类 - Pager :: Pathing(),这个方法就是从Pager上扩展而来,满足了当时的需求.

作者: volcano 发表于9月 22, 2006 at 7:16 am

TOP

Pear :: Pager和AJAX的整合应用

作为一个PHP开发人员来说,大概很让人受用的一个东东就是Pear的类库了。我们知道,Pear :: Pager是专门处理分页的,而Pear :: HTML_AJAX则是Ajax应用的一些类库。但是Pager也不仅仅是只能用于html的分页链接,它已经为比超女还红的Ajax做好了准备,下面看看这两个包如何整合应用。

Pager and Javascript
现在走出第一步,Pager已经能够构建出javascript的链接了,和Ajax整合,理论上应该也是能够实现的,下面是Pager和javascript分页的一个例子:

PLAIN TEXT
复制内容到剪贴板
代码:
<?php
require_once 'Pager/Pager.php';
$data = range(1, 100); //an array of data to paginate
$pager_params = array(
    'mode'     => 'Sliding',
    'append'   => false,  //don't append the GET parameters to the url
    'path'     => '',
    'fileName' => 'javascript:revealDiv(%d)',  //Pager replaces "%d" with the page number...
    'perPage'  => 10, //show 10 items per page
    'delta'    => 5,
    'itemData' => $data,
);
$pager = & Pager::factory($pager_params);
$n_pages = $pager->numPages();
$links = $pager->getLinks();
?>
<html>
<head>
    <script type="text/javascript" language="javascript">
    var n_pages = <?php echo $n_pages ?>;
    function revealDiv(n)
    {
        for (var count = 1; count <= n_pages; count++) {
          document.getElementById("page"+count).style.display = 'none';
        }
        document.getElementById("page"+n).style.display = 'block';
    }
    </script>
    <style type="text/css">
    div.page {
      background: #FFFF99;
      border-top: 1px solid #FFBF99;
      border-bottom: 1px solid #FFBF99;
    }
    </style>
</head>
<body>
<h1>PEAR::Pager example with JavaScript</h1>
<?php echo $links['pages']; ?>
<hr />
<?php
for ($i=1; $i <= $n_pages; ++$i) {
    echo '<div class="page" id="page'.$i.'">';
    echo '<h2>Page '.$i.'</h2>';
    foreach ($pager->getPageData($i) as $item) {
        echo 'Item '.$item.'<br />';
    }
    echo '</div>';
}
?>
<hr />
<script type="text/javascript" language="javascript">
revealDiv(1);
</script>
</body>
</html>
例子中把分页的所有数据放入一个div标签,定义了两个比较重要的参数就是path(为空)和fileName,fileName原本应该是链接的文件名,但是这里用javascript替换了。

Ajax上阵
这个例子包括三个文件page.html,server.php,testdata.php


page.html
用动态javascript--server.php来处理数据,调用HTML_AJAX.replace('target', 'testdata.php')来替换id为target这个div的内容。

PLAIN TEXT
PHP:
复制内容到剪贴板
代码:
<html>
<body>
<h1>PEAR::Pager example with AJAX</h1>

<script type="text/javascript" src="server.php?client=all"></script>

<div id="target">I'm the target</div>


<script type="text/javascript">
    HTML_AJAX.replace('target', 'testdata.php');
</script>


</body>
</html>
testdata.php
这是个很简单的php程序,取到分页数据并输出html

PLAIN TEXT
PHP:
复制内容到剪贴板
代码:
<?php
require_once 'Pager/Pager.php';
$data = range(1, 100); //an array of data to paginate
$pager_params = array(
    'mode'     => 'Sliding',
    'append'   => false,  //don't append the GET parameters to the url
    'path'     => '',
    'fileName' => 'javascript:HTML_AJAX.replace(\'target\',\'testdata.php?pageID=%d\');',  //Pager replaces "%d" with the page number...
    'perPage'  => 10, //show 10 items per page
    'delta'    => 1,
    'itemData' => $data,
);
$pager = & Pager::factory($pager_params);
$n_pages = $pager->numPages();
$links = $pager->getLinks();
echo '<p>This container is loaded with an AJAX call</p>';
echo '<p><span class="datetime">DateTime: '. date('Y-m-d H:i:s') .'</span></p>';
echo '<h3>Page '. $pager->getCurrentPageId() .'</h3>';
foreach ($pager->getPageData() as $item) {
    echo 'Item '. $item .'<br />';
}
echo '<hr />'.$pager->links;
?>
最后,贴上幕后工作者server.php的代码
用HTML_AJAX_Server来处理ajax这些烦心事吧

PLAIN TEXT
PHP:
复制内容到剪贴板
代码:
<?php
include 'HTML/AJAX/Server.php';

$server = new HTML_AJAX_Server();
$server->handleRequest();
?>
web 2.0, Ajax的趋势图

时下的web 2.0和Ajax概念正是如火如荼,且不论Ajax这东东到底是不是炒作的产物,就实际应用来说,Ajax在某些场合的确是顶好用而且看上去挺酷.

蓝的是web 2.0,红的是Ajax


参考文档
http://www.alberton.info/pear_pa ... ipt_navigation.html

作者: volcano 发表于10月 23, 2006 at 7:53 am

TOP

Pear的PHP_Compat包

Pear的PHP_Compat是个比较有趣的包,它提供了一些php4下也能使用的php5专有函数,比如file_put_contents,array_combine,str_split..........这样即使是在php4的主机上,也能提前享受一点php5函数的便利.

用法
PLAIN TEXT
PHP:
复制内容到剪贴板
代码:
<?php
require_once 'PHP/Compat.php';

// load file_put_contents
PHP_Compat::loadFunction('file_put_contents');

// load str_split, array_chunk and file_get_contents
PHP_Compat :: loadFunction(array('str_split', 'array_chunk', 'file_get_contents'));
?>
上面的例子说明,可以一次载入n个php5特有函数

Package Information: PHP_Compat
http://pear.php.net/package/PHP_Compat

TOP

如何使用PHP和PEAR进行不同时区的转换

PHP具备一系列日期和时间函数,这为您获取时间信息提供了便利,您可以将这些信息转换为需要的格式并用于计算或者展示给用户。但是如果您想实现一些复杂的功能,事情可能会变得非常复杂。

    一个简单的例子是在网页上显示时间。在PHP中,您可以简单地使用data()函数读取服务器的时钟并以指定的格式进行显示;但是如果您所要显示的时间是不同时区的,比如,您的公司和服务器位于不同的国家,您需要看到的是本地时间而不是当地时间。

    因此,您需要计算出两地的时差,并进行一些计算从而在不同的时区中进行调整,如果时差很重要,您还需要考虑到日期变更、夏令时、月底的最后一天以及闰年的限制等等。

    正如您想像的一样,如果您手动完成这些时区的数学计算,那么这很快就会变成一件很复杂的事情。幸好,PHP内建的时区函数可以帮助解决这一问题,但这些函数并不直观,需要一些时间来熟悉它们的使用。当然,更加快捷的一个选择是使用PEAR的Date类库,它具备对时区的内建支持,而且到目前为止,这是进行时区转换的最简便的方法。

    这篇指南将向您讲解如何使用PEAR的Date类在不同的时区中进行不同的时间数值转换。我假定您已经安装了Apache、PHP以及PEAR的Date类库并且它们都能正常工作。

    注意:您可以直接从互联网上安装PEAR的Date类库,您可以下载或使用它提供的指南进行安装。

开始

    让我们从基础的初始化和使用Date对象开始讲解,请创建列表A中的PHP代码:
复制内容到剪贴板
代码:
<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2006-06-21 15:45:27");

// retrieve date
echo $d->getDate();
?>
这个例子非常简单,它所包含的类代码使用一个日期/时间字符串初始化了一个Date()对象,然后使用getDate()方法来展示您插入的数值,以下是输出的结果:

    2006-06-21 15:45:27

    如何以不同格式来显示日期呢?如果是一个标准格式,比如ISO格式,那只需要向getDate()传递一个修饰符来指明即可,代码如列表B所示:
复制内容到剪贴板
代码:
<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2006-06-21 15:45:27");

// retrieve date as timestamp
echo $d->getDate(DATE_FORMAT_ISO_BASIC);
?>
这个例子的输出符合标准的ISO格式。

    20060621T154527Z

    如果需要自己定制的格式,您可以使用format()方法来实现这一点,它和PHP的原有的date()函数一样,format()方法可以接收一系列格式定义符来指明日期每个部分的具体格式。列表C展示了使用format()方法的例子(您可以参考类文档来获取格式定义符的完整列表)。
复制内容到剪贴板
代码:
<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2006-06-21 15:45:27");

// retrieve date as formatted string
echo $d->format("%A, %d %B %Y %T");
?>
输出的结果如下:

    Wednesday, 21 June 2006 15:45:27

时区间进行转换

    现在您已经了解了基本的使用方法,下面让我们来讨论时区的问题,一旦您拥有了初始化的Date()对象,转换时区的工作就可以分为两个简答的步骤:

    使用setTZByID()方法告知Date类从哪个时区进行转换;
    然后,使用convertTZByID()方法告知Date类您所转换的目标时区。


    列表D展示了这部分代码:
复制内容到剪贴板
代码:
<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2006-06-21 10:36:27");

// set local time zone
$d->setTZByID("GMT");

// convert to foreign time zone
$d->convertTZByID("IST");

// retrieve converted date/time
echo $d->format("%A, %d %B %Y %T");
?>
在这个例子中,我将格林威治标准时间(GMT)转换为印度标准时间(IST),印度时间比格林威治时间早5.5小时,因此该脚本输出的结果是:

    Wednesday, 21 June 2006 16:06:27

    是不是很简单?以下列表E的例子展示了如果处理闰年和月底日期的问题:
复制内容到剪贴板
代码:
<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2008-03-01 06:36:27");

// set local time zone
$d->setTZByID("GMT");

// print local time
echo "Local time is " . $d->format("%A, %d %B %Y %T") . "\n";

// convert to foreign time zone
$d->convertTZByID("PST");

// retrieve converted date/time
echo "Destination time is " . $d->format("%A, %d %B %Y %T");
?>
输出如下:

    Local time is Saturday, 01 March 2008 06:36:27

    Destination time is Friday, 29 February 2008 22:36:27

    注意:您可能会奇怪时区ID是从何而来的,其实,您可以在类文档中找到时区ID的完整列表。

计算格林威治标准时间位移

    另外一个比较有效的方法是使用格林威治标准时间的位移量来转换时区,也就是利用指定时区和格林威治标准时间之间的差值来进行计算,PEAR的Date类为这一功能提供了便利,通过getRawOffset()方法就可以实现这一点,列表F展示了一个例子。
复制内容到剪贴板
代码:
<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2006-06-21 10:36:27");

// set local time zone
$d->setTZByID("PST");

// get raw offset from GMT, in msec
echo $d->tz->getRawOffset();
?>
在此,getRawOffset()方法计算了本地时间和格林威治标准时间的差值,输出结果如下:

    -28800000

    需要注意的是,位移量是以毫秒为单位进行计算的,所以您需要将它除以3600000(每小时中的毫秒数)来获取时区间相差的小时数。

    技巧:您可以使用inDaylightTime()来查看目标时区是否正处于夏令时状态,在类库文档中有关于此方法的详细信息。

添加和减少时间跨度

    您可以通过Date类库对时间数值执行复杂的日期计算,添加或者减少日期/时间数值,这些持续时间(时间跨度)可以表示为一个包含日、小时、分钟和/或秒的字符串组件,列表G展示了一个简单的例子。
复制内容到剪贴板
代码:
<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2006-06-21 15:45:27");

// add 01:20 to it
$d->addSpan(new Date_Span("0,1,20,0"));

// retrieve date as formatted string
echo $d->format("%A, %d %B %Y %T");
?>
在这个例子中,通过调用Date类的addSpan()方法和Date_Span()对象,我向初始的时间戳添加了1小时20分钟,输出结果显而易见:

    Wednesday, 21 June 2006 17:05:27

    和添加时间跨度一样,您可以使用减法,实际上,这就是subtractSpan()方法的目的,列表H展示了此方法的使用方法。
复制内容到剪贴板
代码:
<?php
// include class
include ("Date.php");

// initialize object
$d = new Date("2006-06-21 15:45:27");

// add 01:20 to it
$d->addSpan(new Date_Span("0,1,20,0"));

// subtract 00:05 from it
$d->subtractSpan(new Date_Span("0,0,5,0"));

// retrieve date as formatted string
echo $d->format("%A, %d %B %Y %T");
?>
在这个例子中,我首先添加了1小时和20分钟,然后又减去了5分钟,最终结果是添加了1小时和15分钟,输出结果如下:

    Wednesday, 21 June 2006 17:00:27

    正如上述的这些例子所展示的,PEAR的Date类库提供了直观而且高效的方法来执行复杂的日期计算,如果您正在寻找一种在不同位置转换时间戳的简便方法,那么我热忱地向您推荐这种方法。


    (Builder.com.cn原创文章版权所有,未经许可严禁转载)

TOP

PEAR:创建中间的数据库应用层

内容:

一、 什么是DB类
二、 为什么要设计抽象的中间数据层
三、 DB的使用入门
四、 DB_Common 使用参考
五、 更进一步,创建你自己的中间数据库应用层
六、 DB的不足
七、参考资源
关于作者


相关内容:

1、用PEAR来写你的下一个php程序
2、常用模块
3、使用PHPDoc轻松建立你的PEAR文档





潘凡 (nightsailer@hotmail.com)
北京赛迪网信息技术有限公司
2001 年 8 月

对于PHP的应用程序来说,90%以上需要和数据库来打交道。那么,你是如何操纵数据库的?当你的后端数据库升级或变迁后,你的这些程序是否能够随之平滑地升级和挂接呢?如果你正在考虑这个问题,那么不妨和我来讨论一下,如何使用PEAR中的DB类来创建与数据库无关的数据库应用层。
一、 什么是DB类
我们首先简单地了解一下DB类。DB类是PEAR中进行数据操作的几个类的集合,它的主要目的是提供一个统一的,抽象的数据接口,这个接口与后端的数据库是无关的。因此,如果你的应用程序使用这个通用的接口来进行数据库的操作,那么就能够平滑地切换到不同的数据库下面,如MYSQL,SQL,SYBASE等等。实际上,DB类希望能够起到简单的类似ODBC或者是PERL中的DBI的作用。说到这里,不得不提一下PHP中的另一个优秀的库:ADODB。ADODB也和DB一样,提供了一个抽象的中间层,而且ADODB所支持的后端数据库要比DB多(至少目前如此),不过ADODB没有直接使用PEAR的一些特性,只是吸取了PEAR的许多思想,包括DB,因此二者的使用方法有许多相似的地方。我不想评论二者孰优孰劣,大家可以根据个人的喜好来使用。

二、 为什么要设计抽象的中间数据层
在详细讨论DB的使用之前,我们先讨论一下为什么要设计中间的数据层,因为这意味着你需要作出一些牺牲和让步,比如,你需要多写一些代码,有的局限于特定数据库的特性将无法直接使用。

我们回忆一下我们过去的做法,如何连接到MYSQL数据库?这的确是个小儿科的问题,下面的代码你一定很熟悉:
复制内容到剪贴板
代码:
<?php
/**
  * 连接到MYSQL数据库
  */
  $host   = "localhost";

  $user   = "root";
  $passwd = "";
  $persistent = 1;

  if ($persisternt){
     $conn = mysql_connect($host,$user,$passwd);
  }else {
     $conn = mysql_pconnect($host,$user,$passwd);
  }
?>
好了,现在建立了数据库连接,我们可以使用它来进行数据库的操作,我们可能使用类似的代码:
复制内容到剪贴板
代码:
<?php
function sql_exec($sql) {
    global $db_Name;
    $result = mysql_db_query($db_dbName,$sql);
    if (!$result) {
            echo mysql_errno(). ": ".mysql_error(). "<br>$sql<br>";
            exit();            
    }
    return $result;
}
$db_Name = "test";
$sql = "select * from users";
$result = sql_exec($sql);
while( $row = mysql_fetch_row($result) ){
    echo "姓名:$row[0] 性别:$row[1] 年龄 $row[2]<br>";
}
mysql_free_result($result);
?>
看起来很不错,是吗?你可能在你的代码里使用很多类似的代码片段。但是,不要太高兴,问题来了。假如,突然,你的数据库需要从MYSQL迁移到别的数据库平台,比如ORACLE,SYBASE。迁移的原因很多,也许是你的老板突发奇想,认为这样能卖个好价钱,或者是你的数据猛增,导致MYSQL的性能下降,总之,迁移是事在必行了。你怎么做,你也许会想,呵呵,这简单,把相关的函数替换一下不就行了。

听起来简单,但是……首先,连接数据库的函数要改,需要把mysql_connect和mysql_pconnect替换成OCILogon和OCIPLogon。mysql_errno和mysql_error()当然不能使用,你需要从OCIError()返回的数组中提取响应的信息。

这还不是太糟,最糟的是相关的mysql_fetch_row,mysql_fetch_array等语句遍布于你的许多代码函数和过程中,你需要逐一查找,分析,然后重新替换或者编写相应的ORACLE的版本。如果,你的数据库操作是集中在一个某一个模块或类中,这项工作还可以接受,否则,等于你重新阅读和修改了绝大部分的代码。即使这个不幸的人不是你,那么他也会暗地里诅咒你的;=)

以上,我们回忆了我们以前的做法,以及可能带来的不幸。那么,如果使用DB类来做类似的操作,应该是什么样的呢?下面是相应的DB版本代码:
复制内容到剪贴板
代码:
<?php
include_once "DB.php";
/*
* 连接到数据库
*/
   $db_host = "localhost";
   $db_user = "root";
   $db_passwd = "";
   $db_dbName = "test";
   $PersistentConnection = 1 ;
   $db_type ="mysql";
   $db_proto ="";
   $db = DB::connect("$db_type://$db_user@$db_passwd:$db_host/$db_dbName",$db_options);
   if( DB::isError($db) ){
       die "无法连接数据库,错误原因:".DB::errorMessage($db);
   }
function sql_exec($sql) {
    global $db;
    $result = $db->query($sql);
    if (DB::isError($result)){
        echo "发生数据库错误:".DB::errorMessage($result);
        exit();
    }
    return $result;
}   
/////////////////////////////////////////////
$sql = "select * from users";
$result = sql_exec($sql);
while( $row = $result->fetchRow() ){
    echo "姓名:$row[0] 性别:$row[1] 年龄 $row[2]<br>";
}
?>
除了连接数据库部分,其他的看起来只是有一些微小的变化,出错处理使用的是PEAR类似的方式(isError),实际上也是从PEAR继承来的。同样的情况,如果你要把数据库从mysql迁移到别的形式,这次假如说是PostegreSQL,一个LINUX中很优秀的数据库,你所做的只是改变一行代码:
   $db_type ="mysql";
变成:
   $db_type ="pgsql";


其他的,不用变动。怎么样,升级的感觉是不是很清爽呢,你可以用剩下的时间好好研读其余的代码,或者和我继续往下讨论DB的使用方法。

三、 DB的使用入门
DB类由3部分组成:

DB.php 这是前端接口,在DB类里提供了许多"静态"的公用方法,我们一般只需要INCLUDE_ONCE这个文件就可以了。
DB/common.php 这是后端数据库的通用抽象类,不同的数据库的后端类需要继承并实现这个类中定义的公用方法和属性,如果你的数据库不被支持,你可以自己编写一个支持类,这样,你的应用程序就可以迁移过来了。
DB/storage.php 这是一个辅助的工具,它可以把SQL查询做为对象返回,同时能够维护这些对象,在对象改变的时候,相应地更新数据库。

DB/ifx.php
   mssql.php  Ms SQL Server支持类
   oci8.php   Orcale 8i支持类
   pgsql.php  PostegreSQL支持类
   sybase.php Sybase支持类
   ibase.php  ibase支持类
   msql.php   mSQL 支持类
   mysql.php  mysql支持类
   odbc.php   odbc 支持类

这些是相应后端数据库的支持类了。相应具体的数据库的操作是由这些支持类来实现的。

下面,我们首先详细介绍DB.PHP中的一些"静态"方法:

connect()方法
这个方法是最重要的静态方法了,我们通过得到一个DB_COMMON对象,并且连接到相应的数据库。这个方法的原型如下:
function &connect($dsn, $options = false)
$dsn是数据源名称(data source name)的缩写,可以是字符串,或者是特定的数组形式。

一般来说,$dsn是一个字符串,它的格式如下:
phptype(dbsyntax)://username:password@protocol+hostspec/database

     *  phptype:  php后端数据库的类型名称(如mysql, odbc 等等.)

TOP

如何用PHP脚本和PEAR类创建ZIP档案文件

在开发Web应用程序时,很有可能您会遇到不同格式的文件——CSV数据、密码文件、XML编码的内容和不同形式的二进制的数据。您的PHP脚本将需要频繁地和这些文件交互,从中读取数据和将数据写入其中。由于有这么些格式的文件要处理,所以您就不要意外PHP中有那么多种类型的内置函数和外部的库,用来连接和使用几乎所有您能说出名称的文件格式。

这篇指南就是关于这样一种文件格式的,可能应用程序开发者几乎每天都会遇到这种文件:ZIP格式。一般这种格式是用来通过电子邮件和远程连接传输文件的,能够将多个文件压缩到一个档案文件中,因此,减少了文件的硬盘占据空间,并且能够更容易地移动它们。PHP通过它的ZZipLib插件和PEAR的Archive_Zip类都可以读取和创建这些ZIP文件。

我将假设您已经有了正常运行的Apache,安装了PHP,并且PEAR Archive_Zip class类已经正确安装了。

注意:您可以直接从网上安装PEAR Archive_Zip程序包,要么下载它,还可以利用提供的指示。

创建ZIP档案文件

让我们从一个简单的例子开始:动态地创建一个包括几个其他文件的ZIP档案文件。以列表A中的脚本开始。

列表A
复制内容到剪贴板
代码:
<?php
include ('Archive/Zip.php');        // imports

$obj = new Archive_Zip('test.zip'); // name of zip file

$files = array('mystuff/ad.gif',
               'mystuff/alcon.doc',
               'mystuff/alcon.xls');   // files to store

if ($obj->create($files)) {
    echo 'Created successfully!';
} else {
    echo 'Error in file creation';
}
?>
这个脚本非常简单,但是值得仔细看一下:

首先,第一步是创建一个Archive_Zip类的实例,然后用将要创建的档案文件的路径和名称将其初始化。在这个例子中,档案文件被命名为test.zip,位于当前目录下。
接着,初始化一个数组,列出将要被压缩的文件,和它们在硬盘中的位置一起保存其中;这些位置用绝对或相对术语列入,但是,一个关键的要考虑的事项是脚本对那些文件或磁盘的位置要有读取的权限。

最后,用create()方法通过压缩和合并指定的文件来实际构建档案文件。这个方法接受文件列表作为输入,然后返回一个布尔逻辑值指示档案文件是否被成功创建。注意脚本在文件被创建的目录下必须有写入特权是非常重要的,否则create()方法将失败;这是一个普遍的,也让大部分新手失败的错误。

现在,在修改了源文件列表和目标文件位置来反映您的本地系统配置之后,试着运行上面的脚本。如果一切顺利的话,Archive_Zip应该可以找到您所列出的、并压缩到名为test.zip的ZIP档案文件中的文件。

查看ZIP档案文件的内容

那么怎么样看到现有的ZIP档案文件中的内容呢?Archive_Zip lets让您通过它的listContent()方法也可以做到这一点。下面是一个例子(列表B):

列表B
复制内容到剪贴板
代码:
<?php
include ('Archive/Zip.php');        // imports

$obj = new Archive_Zip('test.zip'); // name of zip file

$files = $obj->listContent();       // array of file information

foreach ($files as $f) {
    foreach ($f as $k => $v) {
        echo "$k: $v\n";
    }
    echo "\n";
}
?>
listContent()的输出是一个由数组组成的结构数组,每一个数组元素代表档案文件中的一个单独文件。通常,每一个元素中保存有相关的信息,例如对应文件的名字、它的索引位置、状态、大小(压缩后和压缩前的)和最近一次修改的时间。用一个循环可以很容易地将这些信息提取出来,还可以像列表B那样,重定它的格式,使其更好传输。下面是输出的一个示例(列表C):

列表C

filename: mystuff/alcon.xls
stored_filename: mystuff/alcon.xls
size: 113664
compressed_size: 35902
mtime: 1141996836
comment:
folder:
index: 0
status: ok

向现有的ZIP档案文件中添加新文件

Archive_Zip类的一个有意思的特性就是它可以通过add()方法向现有的档案文件中添加新的文件。为了说明这一点,让我们回到test.zip,尝试对它添加新文件(列表D):

列表D
复制内容到剪贴板
代码:
<?php
include ('Archive/Zip.php');        // imports

if (file_exists('test.zip')) {
    $obj = new Archive_Zip('test.zip'); // name of zip file
} else {
    die('File does not exist');
}

$files = array('otherstuff/montecarlo.png');   // additional files to store

if ($obj->add($files)) {
    echo 'Added successfully!';
} else {
    echo 'Error in file addition';
}
?>
正如您所看到的那样,向一个现有的档案文件中添加新文件的程序和创建一个新的档案文件十分相似:初始化一个新的Archive_Zip对象指向问号代表的档案文件,创建一个数组代表将要添加的文件的列表,然后将这个数组输入add()方法。和create()方法一样,add()返回一个布尔逻辑信号来指示添加是否成功。和前面一样,一个主要的问题就是别忘了要有足够的权限:记得确保脚本有适当的权限来读取源文件,并将新压缩的档案文件写回到硬盘中。

从现有的ZIP档案文件中删除文件

和添加文件一样,您也可以删除文件。Archive_Zip类具有delete()方法,让您能够从现有的档案文件中移除文件。列表E说明了这一点。.

列表E
复制内容到剪贴板
代码:
<?php
include ('Archive/Zip.php');        // imports

if (file_exists('test.zip')) {
    $obj = new Archive_Zip('test.zip'); // name of zip file
} else {
    die('File does not exist');
}

$files = array('mystuff/ad.gif', 'otherstuff/montecarlo.png');   // files to delete

if ($obj->delete(array('by_name' => $files))) {
    echo 'Deleted successfully!';
} else {
    echo 'Error in file deletion';      
}
?>
在这里,创建了一个待删除文件的数组,然后将其输入delete()方法。注意delete()调用中的特殊参数“by_name”:这告诉Archive_Zip只删除那些与文件名精确匹配的文件。如果删除成功,delete()方法返回真。

除了这种形式的有选择的删除之外,delete()方法也支持对与特定类型或正则表达式相匹配文件的大规模的摧毁。利用“by_ereg”或“by_preg”参数,Perl和PHP的正则表达式都支持。列表F是一个例子,用来说明怎样用这种方法,通过利用Perl的正则表达式来删除一个档案文件中所有的*.doc文件。

列表F
复制内容到剪贴板
代码:
<?php
include ('Archive/Zip.php');        // imports

if (file_exists('test.zip')) {
    $obj = new Archive_Zip('test.zip'); // name of zip file
} else {
    die('File does not exist');
}

if ($obj->delete(array('by_preg' => "/.*doc$/"))) { // all DOC files
    echo 'Deleted successfully!';
} else {
    echo 'Error in file deletion';     
}
?>
如以上的例子所示,PEAR的Archive_Zip类用途很多,只需要几行代码,就使您能够执行一些相当复杂的与ZIP文件的交互。但愿上面的示例脚本能够激发起您的灵感,告诉您如何在您的日常开发活动中使用这个类,并让您对用它进行试验产生兴趣。祝您编程开心!

TOP

PEAR :: HTML_QuickForm与Smarty 的结合应用

Haohappy在《PHP & More》第三期的《PEAR::HTML_QuickForm入门》一文中说过要写QuickForm和Smarty的结合应用,一直没写,今天看到PHPE论坛上有朋友在询问,为自己的懒惰而惭愧。现在补上,希望对大家有点帮助。 在我看来,PEAR::HTML_QuickForm是个非常优秀的表单类库,大大加快了开发速度,我现在的大多数项目都会用到。如果对PEAR::HTML_QuickForm不了解的朋友,建议先看这篇文章。


本文针对的读者为有较丰富开发经验的PHP程序员,要求读者
1. 熟悉PEAR及其安装和使用;
2. 熟悉HTML_QuickForm;
3. 理解模板的概念,熟悉Smarty模板引擎的使用。


在《PEAR::HTML_QuickForm入门》的表单的美化输出一节中,提到了用QuickForm自带的Form修饰方法来美化输出。很明显,这种方法显得有点麻烦,而且让程序员来美化网页,有点难为我们了。 现在程序员和设计师的合作最常见的就是通过模板,所以如何把QuickForm和模板引擎相结合,这就是我们需要解决的问题。其实QuickForm可以和多种模板引擎相结合,如ITX, Sigma, Flexy, Smarty等,每种模板都有其优点和缺点,目前Smarty是最通用的模板引擎,所以我们把QuickForm和Smarty的结合作为重点来研究。

首先,给大家看看我们的最后效果:



这个例子非常简单,只有一个Form,4个Input,只是用来讲解QuickForm的使用。在实际开发中,我们经常遇到几十个Input的情况。实际上,表单越复杂,就越显出我们传统的处理方式的低效,就越显出QuickForm的强大。这一点,也许大家以后会体会到。


好,开始我们的QuickForm Smarty之旅。
changPwd.php
复制内容到剪贴板
代码:
<?

require_once("includes/config.inc.php");

//构建Smarty对象

$smarty = new Smarty_App;

$smarty->assign('CSSDIR','./templates/admin');

$smarty->assign('title',':: Haohappy Test网站管理系统 ::');



//构建登录表单

$form = new HTML_QuickForm('frmChgPwd', 'post');



//增加表单元素

$form->addElement('password', 'adminPwd', '','class = NameAndPwd');

$form->addElement('password', 'newPwd', '','class = NameAndPwd');

$form->addElement('password', 'newPwd2', '','class = NameAndPwd');

$form->addElement('submit', 'btnSubmit', '修改密码','class = btnSubmit');



//增加验证规则 会自动生成javascript变量,存入javascript验证函数

$form->addRule('adminPwd','密码不能为空!', 'required','','client');

$form->addRule('newPwd','新密码不能为空!', 'required','','client');

$form->addRule('newPwd2','新密码不能为空!', 'required','','client');

$form->addRule(array('newPwd','newPwd2'),"两次输入的密码不同!!",'compare','','client');





if ($form->validate()) {

        //如果表单数据正确,修改密码

        $form->process('changePwd');

}

else{



  //否则显示表单



// 建立renderer对象

$renderer =& new HTML_QuickForm_Renderer_ArraySmarty($smarty );   



// build the HTML for the form 生成表单的HTML代码

$form->accept($renderer);



//assign array with form data 分配表单数据到数组中

$smarty->assign('form_data', $renderer->toArray());

$smarty->catching = false;



// 调试

//echo "<pre>";var_dump($renderer->toArray());echo "</pre>";

$smarty->display("changePwd.tpl");



}



//修改密码

function changePwd(){}     

?>
在代码中,我们用$form->addElement()增添了4个表单元素,用$form->addRule()增加了4条验证规则。怎么样,是不是很快捷方便? 以验证两个密码是否相同的验证规则为例,如果我们自己写验证规则,虽然快,但是代码就会显得臃肿和凌乱,由QuickForm来负责数据验证,开发速度大大提高,而且代码显得很简洁漂亮。仅用了一行代码:

$form->addRule(array('newPwd','newPwd2'),"两次输入的密码不同!!",'compare','','client');

关于QuickForm的好处,请参看《PEAR::HTML_QuickForm入门》,在此不再重复。

下面这行代码就是我们将HTML_QuickForm与Smarty连接的桥梁:

$renderer =& new HTML_QuickForm_Renderer_ArraySmarty($smarty );


所谓renderer,就是用来负责显示的,这里我们把QuickForm的renderer指定为Smarty,我们就可以使用强大的Smarty模板引擎来格式化QuickForm的输出了。

其它:

changePwd()是这个文件的核心操作函数,用来修改密码。
$form->process('changePwd'); //这行代码用来调用changePwd()

//echo "<pre>";var_dump($renderer->toArray());echo "</pre>";
这一行用来调试,我们随时可以把$renderer中的所有变量打印出来,看看程序是否执行正确。

再看我们的模板,也很简单:
复制内容到剪贴板
代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<HTML>

<HEAD>

<TITLE> changePwd.tpl </TITLE>

<META NAME="Generator" CONTENT="EditPlus">

<META NAME="Author" CONTENT="">

<META NAME="Keywords" CONTENT="">

<META NAME="Description" CONTENT="">

<link href="{$CSSDIR}/style.css" rel="stylesheet" type="text/css">

{if $form_data.javascript}

    {$form_data.javascript}

{/if}

</HEAD>



<BODY>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<form {$form_data.attributes} >

<table width="300"  border="0" align="center" cellpadding="3" cellspacing="3" bgcolor="#F6F6F6" style="font-size:9pt" class="AddTable">

<tr bgcolor="#FFFFFF">

  <td width="47%" colspan="2"><div align="center">修改管理员密码</div></tr>

  <tr>

  <tr>

    <td width="47%"><div align="center">现有管理员密码

    </div></td>

    <td width="53%">{$form_data.adminPwd.html}</td>

  </tr>

  <tr>

    <td><div align="center">新密码

    </div></td>

    <td>{$form_data.newPwd.html}</td>

  </tr>

  <tr>

    <td><div align="center">再次输入新密码

    </div></td>

    <td>{$form_data.newPwd2.html}</td>

  </tr>

  <tr>

    <td colspan="2"><div align="center">

      {$form_data.btnSubmit.html}

    </div></td>

  </tr>

</table>

</form>

</BODY>

</HTML>
这两个简单的文件,总共不到100行代码,就完成了我们在文章开头的效果。包含完整的表单数据验证,处理过程。


另:使用QuickForm,可以很方便地实现显示层和逻辑层的分离,因为处理的函数是完全独立出来的。

例如说可以把




if ($form->validate()) {

        //如果表单数据正确,修改密码

        $form->process('changePwd');

}


改装成


if ($form->validate()) {



switch ($post_vars['action']) {



           default:



           case "changPwd":



              $form->process('changePwd');



              break;      



           case "Add":



              $form->process('add');



              break;



         



           case "Update":



              $form->process('update');



              break;



         



           case "Delete":



              $form->process('delete');



              break;              



}


然后把changePwd,add,update,delete四个函数独立到某个文件当中。这样就可以根据页面提交的action来调用不同的操作。


这个想法相对比较简陋一些,如果你要用更强大的功能,还可以试试PEAR::HTML_QuickForm_Controller。HTML_QuickForm_Controller基于PageController设计模式,也就是用单个页面来处理通过GET和POST传递而来的request和 action。这是个非常有意思的想法,但是这种开发模式不适合于新手,因为相对比较复杂。其作者也说:

HTML_QuickForm_Controller is not intended for PHP newbies. If you don't understand what classes are, if you have no prior experience with QuickForm, if you are a fan of copy-paste programming then this package is not for you.

The package is indeed complex, but so are the problems it is trying to solve. Try to rewrite any of the enclosed multipage form examples without using such a package and you'll see what we mean.

这部份暂不讨论,这需要大家对MVC有一定了解,下次有机会再另写文章。我自己目前的开发框架就是个MVC框架,觉得很顺手,显示部份就是交给Smarty QuickForm来完成。希望有更多人关注和使用QuickForm,相信使用之后大家一定不会失望的

TOP

采用 PEAR 来缓冲 PHP 程序(一)

PHP 世界中缓冲是一个热门的话题,因为 PHP 产生的动态页面,每次用户请求都需要重新计算,不论请求的结果是否一样,同时,PHP 每次都会编译一次脚本。这样的超负荷运转对一个流量很高的网站来说肯定难以忍受。幸运的是, Web 的结果可以缓冲,而不需要重新运行和编译脚本,商品化的产品像 ZendCache 或者开源的 Alternate PHP Cache都提供了把 PHP 脚本编译为字节代码并缓冲的办法。

PEAR 的缓冲包提供了缓冲动态内容,数据库查询和 PHP 函数调用的框架。

就像 Perl 有 CPAN, TeX 有 CTAN,PHP 也有自己的中心资源库,存放类,库和模块。这个库称为 PEAR(PHP Extension and Add-On Repository)。

本文假设你已经安装了 PEAR 环境,如果没有的话,可以去 PHP 网站下载。


PEAR 的缓冲包包含一个总体的缓冲类和几个特别的子类。缓冲类使用容器类来存贮和管理缓冲数据。

下面是 PEAR 缓冲当前所包含的容器,以及各自的参数:

file -- file 容器在文件系统存储了缓冲的数据,是最快的容器。

cache_dir -- 这是容器存储文件的目录。

filename_prefix -- 缓冲文件的前缀,例如:"cache_"。

shm -- shm 容器把缓冲数据放入共享内存,基准测试显示,目前的实现下,这个容器的速度要比文件容器慢。

shm_key -- 共享内存使用的键值。

shm_perm -- 使用共享内存数据段的权限。

shm_size -- 分配共享内存的大小。

sem_key -- 信号灯的键值。

sem_perm -- 信号灯的权限。

db -- PEAR 的数据库抽象层。

dsn -- 数据库连接的 DSN 。可以参考 PEAR 的 DB 文档。

cache_table -- 表的名字。

phplib -- phplib 容器使用数据库抽象层存储缓冲。

db_class

db_file

db_path

local_file

local_path

ext/dbx -- PHP 的数据库抽象层扩展,如果像把缓冲存入数据库,可以采用这个容器。

module

host

db

username

password

cache_table

persistent

使用 PEAR Cache 所得到的性能提升取决于你所选择的缓冲容器,例如,把数据库的结果再次存入数据库缓冲中就显得毫无意义。

PEAR Cache 的函数缓冲模块能把任何函数或者方法的结果缓冲,不论是 PHP 的内置函数还是用户自定义函数,他缺省采用文件容器,把缓冲数据放入到一个叫做
function_cache 的目录。


Cache_Function 类的构造器可以有三个可选的参数:

$container :缓冲容器的名字。

$container_options :缓冲容器的数组参数。

$expires:缓冲对象过期的时间(秒数)。

普通的函数调用采用 Cache_Function 类的 call() 方法时,就能触发缓冲。调用 call() 很容易,的一个参数是函数的名字,然后是函数的参数,第二个参数是要调用函数中的第一个,依此类推,我们来看例子:

例 1: 缓冲函数和方法的调用



// 调用 PEAR Cache 的函数缓冲。
复制内容到剪贴板
代码:
<?php
require_once ’Cache/Function.php’;

// 定义一些类和函数。

class foo {
function bar($test) {
echo "foo::bar($test)
";
}
}

class bar {
function foobar($object) {
echo ’$’.$object.’->foobar(’.$object.’)
’;
}
}

$bar = new bar;

function foobar() {
echo ’foobar()’;
}

// 取得 Cache_Function 对象

$cache = new Cache_Function();

// 对 foo 类的静态函数 bar() 作缓冲(foo::bar())。
$cache->call(’foo::bar’, ’test’);

// $bar->foobar()
$cache->call(’bar->foobar’, ’bar’);

$cache->call(’foobar’);
?>
下面我们采用 Cache_Output 来把输出作缓冲:

例子 2: 缓冲脚本的输出


// 加载 PEAR Cache 的输出缓冲
复制内容到剪贴板
代码:
<?php
require_once ’Cache/Output.php’;

$cache = new Cache_Output(’file’, array(’cache_dir’ => ’.’) );

// 计算要缓冲页面的标记,我们假定页面的缓冲取决于
// URL, HTTP GET 和 POST 变量以及 cookies。

$cache_id = $cache->generateID(array(’url’ => $REQUEST_URI, ’post’ => $HTTP_POST_VARS, ’cookies’ => $HTTP_COOKIE_VARS) );

// 查询缓冲

if ($content = $cache->start($cache_id)) {

// 缓冲命中
echo $content;
die();
}

// 缓冲丢失

// -- 在这里插入内容产生代码 --

// 把页面存入缓冲
echo $cache->end();
?>
利用 Cache_Output 类,很容易把一个动态的数据库驱动的网站应用转化为静态,从而极大的提升站点的性能。

越来越多的站点在采用 GZIP 压缩 HTML 内容,这样减少了服务器的带宽消耗,对于使用 Modem 上网的用户来说也能受益不少。

Cache_OutputCompression 扩展了 Cache_Output 类的功能,他把 GZIP 压缩的 HTML 内容进行缓冲,从而节省了 CPU 压缩的时间。

TOP

 11 12
发新话题