php

CentOS 5.4 yum安装Apache+php+Mysql

Centos 里的 yum 在线安装很慢.以下是替换为中国CentOS镜像服务器!
中国官方镜像网站: http://centos.ustc.edu.cn/
/* 使用说明 */
cd /etc/yum.repos.d  [进入yum.repos.d目录]
mv CentOS-Base.repo CentOS-Base.repo.save   [修改源文件名称备份]
wget http://centos.ustc.edu.cn/CentOS-Base.repo.5  [下载]
mv CentOS-Base.repo.5 CentOS-Base.repo     [下载后的文件更名]

1. 更新系统内核到最新.
yum -y update
系统更新后,如果yum安装时提示错误信息,请执行以下命令修复.
rpm –import /etc/pki/rpm-gpg/RPM-GPG-KEY*

2. 安装Apahce, PHP, Mysql, 以及php连接mysql库组件

yum -y install httpd php mysql mysql-server php-mysql

//安装mysql扩展
yum -y install mysql-connector-odbc mysql-devel libdbi-dbd-mysql
//安装php的扩展
yum -y install php-gd php-xml php-mbstring php-ldap php-pear php-xmlrpc
//安装apache扩展
yum -y install httpd-manual mod_ssl mod_perl mod_auth_mysql

一次性粘贴安装:
yum -y install httpd php mysql mysql-server php-mysql httpd-manual mod_ssl mod_perl mod_auth_mysql php-mcrypt php-gd php-xml php-mbstring php-ldap php-pear php-xmlrpc mysql-connector-odbc mysql-devel libdbi-dbd-mysql

3. 启动服务配置

/sbin/chkconfig httpd on [设置apache为自启动]
/sbin/chkconfig mysqld on [mysqld服务]

/sbin/service httpd start [自启动 httpd 服务]
/sbin/service mysqld start [自启动mysqld服务]

4.设置mysql数据库root帐号密码。
mysqladmin -u root password ‘新密码’ [引号内填密码]

让mysql数据库更安全

代码:

mysql -u root -p [此时会要求你输入刚刚设置的密码,输入后回车即可

mysql> DROP DATABASE test; [删除test数据库]

mysql> DELETE FROM mysql.user WHERE user = ”; [删除匿名帐户]

mysql> FLUSH PRIVILEGES; [重载权限]

mysql> GRANT ALL PRIVILEGES ON *.* TO ‘root’@’192.168.1.13’ IDENTIFIED BY ‘密码’ WITH GRANT OPTION; [增加远程链接用户]

按照以上的安装方式, 配置出来的默认站点目录为/var/www/html/

测试环境

rpm -qa |grep mysql

rpm -qa |grep httpd

rpm -qa |grep php

5.配置文件存放的位置

apache配置文件存放的位置:/etc/httpd/conf/httpd.conf

php配置文件存放的位置:/etc/php.ini 和/etc/php.d里面的文件

mysql配置文件存放的位置:/etc/my.cnf

6、安装phpMyAdmin

进入phpMyAdmin官方下载(不要最新版本,下phpMyAdmin 2.11.9.5
就行了,3.1以上需php 5.2以上),上传到你的网站目录下,然后进行配置。只需几步即可搞定。

I. config.sample.inc.php更名为config.inc.php;

II. 打开config.inc.php文件,进行以下修改;

// $cfg[‘Servers’][$i][‘controluser’] = ‘pma’;

// $cfg[‘Servers’][$i][‘controlpass’] = ‘pmapass’;

// $cfg[‘Servers’][$i][‘pmadb’] = ‘phpmyadmin’;

// $cfg[‘Servers’][$i][‘bookmarktable’] = ‘pma_bookmark’;

// $cfg[‘Servers’][$i][‘relation’] = ‘pma_relation’;

// $cfg[‘Servers’][$i][‘table_info’] = ‘pma_table_info’;

// $cfg[‘Servers’][$i][‘table_coords’] = ‘pma_table_coords’;

// $cfg[‘Servers’][$i][‘pdf_pages’] = ‘pma_pdf_pages’

// $cfg[‘Servers’][$i][‘column_info’] = ‘pma_column_info’;

// $cfg[‘Servers’][$i][‘history’] = ‘pma_history’;

// $cfg[‘Servers’][$i][‘designer_coords’] = ‘pma_designer_coords’;

去掉每行前面的//;

II.$cfg[‘blowfish_secret’] = ”; |修改为| $cfg[‘blowfish_secret’] = ‘http’;

IV.$cfg[‘Servers’][$i][‘controluser’] = ‘pma’; |把’pma’修改为你的帐号|$cfg[‘Servers’][$i][‘controlpass’] = ‘pmapass’; |把’pmapass设置为你的mysql登录密码|

V. $cfg[‘blowfish_secret’] = ”; | 添加短语密码例如:$cfg[‘blowfish_secret’] = ‘onohot’;

PHP 遍历数组的常用方法

1. foreach()
foreach()是一个用来遍历数组中数据的最简单有效的方法。

#example1:

<?php
$colors = array(‘red’,’blue’,’green’,’yellow’);
foreach ($colors as $color) {
    echo “Do you like $color? <br />”;
}
?>

显示结果:

Do you like red?
Do you like blue?
Do you like green?
Do you like yellow?

2. while()
while() 通常和 list(),each()配合使用。

#example2:

<?php
$colors = array(‘red’,’blue’,’green’,’yellow’);
 
while(list($key,$val) = each($colors)) {
    echo “Other list of $val.<br />”;
}
?>
显示结果:

Other list of red.
Other list of blue.
Other list of green.
Other list of yellow.

3. for()
#example3:

<?php
$arr = array (“0” => “zero”,”1″ => “one”,”2″ => “two”);
 
for ($i = 0;$i < count($arr); $i++) {
    $str = $arr[$i];
    echo “the number is $str.<br />”;
}
?>
显示结果:

the number is zero.
the number is one.
the number is two.

========= 以下是函数介绍 ==========

key()
mixed key(array input_array)

key()函数返回input_array中位于当前指针位置的键元素。

#example4

<?php
$capitals = array(“Ohio” => “Columbus”,”Towa” => “Des Moines”,”Arizona” => “Phoenix”);
echo “<p>Can you name the capitals of these states?</p>”;
while($key = key($capitals)) {
    echo $key.”<br />”;
    next($capitals);
//每个key()调用不会推进指针。为此要使用next()函数
}
?>
显示结果:

Can you name the capitals of these states?
Ohio
Towa
Arizona

reset()
mixed reset(array input_array)

reset()函数用来将input_array的指针设置回数组的开始位置。如果需要在一个脚本中多次查看或处理同一个数组,就经常使用这个函数,另外这个函数还常用于排序结束时。

#example5 - 在#example1上追加代码

<?php
$colors = array(‘red’,’blue’,’green’,’yellow’);
foreach ($colors as $color) {
    echo “Do you like $color? <br />”;
}
 
reset($colors);
 
while(list($key,$val) = each($colors)) {
    echo “$key => $val<br />”;
}
?>
显示结果:

Do you like red?
Do you like blue?
Do you like green?
Do you like yellow?
0 => red
1 => blue
2 => green
3 => yellow

注意:将一个数组赋值给另一个数组时会重置原来的数组指针,因此在上例中如果我们在循环内部将 $colors 赋给了另一个变量的话将会导致无限循环。
例如将 $s1 = $colors; 添加到while循环内,再次执行代码,浏览器就会无休止地显示结果。

each()
array each(array input_array)

each()函数返回输入数组当前键/值对,并将指针推进一个位置。返回的数组包含四个键,键0和key包含键名,而键1和value包含相应的数据。如果执行each()前指针位于数组末尾,则返回FALSE。

#example6

<?php
$capitals = array(“Ohio” => “Columbus”,”Towa” => “Des Moines”,”Arizona” => “Phoenix”);
 
$s1 = each($capitals);
print_r($s1);
?>
显示结果:

Array ( [1] => Columbus [value] => Columbus [0] => Ohio [key] => Ohio )

current(),next(),prev(),end()
mixed current(array target_array)

current()函数返回位于target_array数组当前指针位置的数组值。与next()、prev()、和end()函数不同,current()不移动指针。
next()函数返回紧接着放在当前数组指针的下一个位置的数组值。
prev()函数返回位于当前指针的前一个位置的数组值,如果指针本来就位于数组的第一个位置,则返回FALSE。
end()函数将指针移向target_array的最后一个位置,并返回最后一个元素。

#example7

<?php
$fruits = array(“apple”,”orange”,”banana”);
 
$fruit = current($fruits);    //return “apple”
echo $fruit.”<br />”;
 
$fruit = next($fruits);        //return “orange”
echo $fruit.”<br />”;
 
$fruit = prev($fruits);        //return “apple”
echo $fruit.”<br />”;
 
$fruit = end($fruits);        //return “banana”
echo $fruit.”<br />”;
?>
显示结果:

apple
orange
apple
banana

=========== 下面来测试三种遍历数组的速度 ===========

一般情况下,遍历一个数组有三种方法,for、while、foreach。其中最简单方便的是foreach。下面先让我们来测试一下共同遍历一个有50000个下标的一维数组所耗的时间。

测试环境:
Intel Core Due2 2GHz
2GB 1067MHz DDR3
Mac OS X 10.5.7
Apache 2.0.59
MySQL 5.0.41
PHP 5.2.6

#example8

<?php
$arr = array();
for($i = 0; $i < 50000; $i++){
$arr[] = $i*rand(1000,9999);
}
 
 
function GetRunTime()
{
list($usec,$sec)=explode(” “,microtime());
return ((float)$usec+(float)$sec);
}
######################################
$time_start = GetRunTime();
 
for($i = 0; $i < count($arr); $i++){
$str = $arr[$i];

 
$time_end = GetRunTime();
$time_used = $time_end – $time_start;
 
echo ‘Used time of for:’.round($time_used, 7).'(s)<br /><br />’;
unset($str, $time_start, $time_end, $time_used);
######################################
$time_start = GetRunTime();
 
 
while(list($key, $val) = each($arr)){
$str = $val;
}
$time_end = GetRunTime();
$time_used = $time_end – $time_start;
echo ‘Used time of while:’.round($time_used, 7).'(s)<br /><br />’;
unset($str, $key, $val, $time_start, $time_end, $time_used);
######################################
$time_start = GetRunTime();
foreach($arr as $key => $val){
$str = $val;
}
 
$time_end = GetRunTime();
$time_used = $time_end – $time_start;
echo ‘Used time of foreach:’.round($time_used, 7).'(s)<br /><br />’;
 
?>
测试结果:

Used time of for:0.0228429(s)

Used time of while:0.0544658(s)

Used time of foreach:0.0085628(s)

经过反复多次测试,结果表明,对于遍历同样一个数组,foreach速度最快,最慢的则是while。从原理上来看,foreach是对数组副本进行操作(通过拷贝数组),而while则通过移动数组内部指标进行操作,一般逻辑下认为,while应该比foreach快(因为foreach在开始执行的时候首先把数组复制进去,而while直接移动内部指标。),但结果刚刚相反。原因应该是,foreach是PHP内部实现,而while是通用的循环结构。所以,在通常应用中foreach简单,而且效率高。在PHP5下,foreach还可以遍历类的属性。

PHP网站开发方案

一、 开发成员

a)项目主管
b)页面美工
c)页面开发
d)服务端程序开发
e)系统与数据管理
f)测试与版本控制

二、 网站组开发简明流程
三、 开发工具与环境

a) 服务器配置
i. WEB服务器: FreeBSD6.1+Apache2.0+PHP5.0,SVN版本控制服务(仅测试机)。
ii. 数据库服务器: WIN2003 server+SQL server 2000+MySQL5.0,CLUSTERED SERVER 集群服务,邮件服务器。
iii. 100M/1000M交换机
b) 开发工具
i. 前台: Macromedia flash 8.0、Macromedia Dreamweaver 8.0、Adobe photoshop CS
ii. 后台: Zend Studio 5.2、SQL Server Enterprise Manager、PhpMyAdmin

四、 技术规则

a) 浏览器兼容策略: 兼容IE5.0以上版本,同时兼容FireFOX2.0以上浏览器。
b) 搜索引擎优化: 着重针对baidu、Google、Yahoo搜索优化,制作清晰明确的网站地图。
c) 字符编码规则: 中文网站一率采用GB2312字符标准。
d) 文件与文件夹命名: 为兼容win32与unix系统,一率采用小写字母命名。
e) 公共文件命名规则:
i. 默认首页: index.htm、index.html、index.php
ii. 主CSS文件: style.css
iii. 主JS文件: main.js
iv. 主程序配置文件:config.php
f) 公共文件目录统一命名
i. 图片目录: /images 或者 /pic
ii. CSS样式目录: /css
iii. JS脚本程序目录:/js
iv. 模板文件目录: /tpl
v. 类或者组件目录:/class 或者 /lib
g) 页面脚本规范: 统一采用JavaScript
h) 代码中的类、函数、变量名:统一使用近似英文单词命名,如:DefaultClass 或者 default_class
i) 代码注释规则:所有程序中的函数或者过程必须加确切的注释。
j) 数据库相关规则
i. 数据表与字段命名规则: 全部小写字母命名,并归类命名前缀,如:用户表组,user_passport、user_info、user_service….
ii. 日期类型字段: 统一使用unix时间戳,char(12)
iii. 主关键字命名: 所有表必须建立以id命名的主键。
k) 模板组件规则: 统一使用兼容版本的Smarty,统一缓存目录,便于Unix下权限控制。
l) 数据库虚拟层: 统一使用Adodb 或 Pdo,SQL语句要兼容现有主流数据库规则。
m) 工厂模式开发规则: 以comm.php为中心开发或继承组件类,统一控制文件调用IO与类的实例化。
n) 面向对象开发规则: 所有函数必须以类 —> 过程的方式存在。
o) SQL封装规则: 所有SQL语句及数据库查询必须存在于过程中。
p) URL转向规则: 为优化搜索引擎,尽量使用Apache的mod_rewrite模块来美化URL,

五、 网站安全与维护策略

a) 服务器与数据库安全:
i. 建立完善的病毒防御机制,安装防火墙,关闭服务器上任何不必要的端口以及服务。
ii. 统一管理用户权限,定期跟踪用户及系统事件,定期查看系统日志。
b) 容灾与备份机制:
i. 建立数据库集群,至少保持一台服务器同步数据,确保意外发生时数据库系统可自动转移到正常的服务器稳定运行。
ii. 定期备份文件及数据,通过各种方式保存数据与文件。
c) 程序安全策略:
i. SQL注入防范:坚决过滤不可预见的非法字符,严格做好数据库查询、更新的SQL语句检验。
ii. 不使用来路不明的第三方源码,不轻易将未知代码拷贝到服务器。

PHP MVC模式的实现

  MVC模式在网站架构中十分常见。它允许我们建立一个三层结构的应用程式,从代码中分离出有用的层,帮助设计师和开发者协同工作以及提高我们维护和扩展既有程式的能力。

视图(View)

“视图”主要指我们送到Web浏览器的最终结果??比如我们的脚本生成的HTML。当说到视图时,很多人想到的是模版,但是把模板方案叫做视图的正确性是值得怀疑的。

对视图来说,最重要的事情可能是它应该是“自我意识(self aware)”的,视图被渲染(render)时,视图的元素能意识到自己在更大框架中的角色。

以XML为例,可以说XML在被解析时,DOM API有着这样的认知??一个DOM树里的节点知道它在哪里和它包含了什么。 (当一个XML文档中的节点用SAX解析时只有当解析到该节点时它才有意义。)

绝大多数模板方案使用简单的过程语言和这样的模板标签:
<p>{some_text}</p>
<p>{some_more_text}</p>
它们在文档中没有意义,它们代表的意义只是PHP将用其他的东西来替换它。

如果你同意这种对视图的松散描述,你也就会同意绝大多数模板方案并没有有效的分离视图和模型。模板标签将被替换成什么存放在模型中。

在你实现视图时问自己几个问题:“全体视图的替换容易吗?”“实现一个新视图要多久?” “能很容易的替换视图的描述语言吗?(比如在同一个视图中用SOAP文档替换HTML文档)”
模型(Model)

模型代表了程序逻辑。(在企业级程序中经常称为业务层(business layer))

总的来说,模型的任务是把原有数据转换成包含某些意义的数据,这些数据将被视图所显示。通常,模型将封装数据查询,可能通过一些抽象数据类(数据访问层)来实现查询。举例说,你希望计算英国年度降雨量(只是为了给你自己找个好点的度假地),模型将接收十年中每天的降雨量,计算出平均值,再传递给视图。
控制器(controller)

简单的说控制器是Web应用中进入的HTTP请求最先调用的一部分。它检查收到的请求,比如一些GET变量,做出合适的反馈。在写出你的第一个控制器之前,你很难开始编写其他的PHP代码。最常见的用法是index.php中像switch语句的结构:
<?php
switch ($_GET[‘viewpage’]) {
    case “news”:
        $page=new NewsRenderer;
    break;
    case “links”:
        $page=new LinksRenderer;
    break;
    default:
        $page=new HomePageRenderer;
    break;
}
$page->display();
?>
这段代码混用了面向过程和对象的代码,但是对于小的站点来说,这通常是最好的选择。虽然上边的代码还可以优化。

控制器实际上是用来触发模型的数据和视图元素之间的绑定的控件。
例子

这里是一个使用MVC模式的简单例子。
首先我们需要一个数据库访问类,它是一个普通类。
<?php
/**
*  A simple class for querying MySQL
*/
class DataAccess {
    /**
    * Private
    * $db stores a database resource
    */
    var $db;
    /**
    * Private
    * $query stores a query resource
    */
    var $query; // Query resource

    //! A constructor.
    /**
    * Constucts a new DataAccess object
    * @param $host string hostname for dbserver
    * @param $user string dbserver user
    * @param $pass string dbserver user password
    * @param $db string database name
    */
    function DataAccess ($host,$user,$pass,$db) {
        $this->db=mysql_pconnect($host,$user,$pass);
        mysql_select_db($db,$this->db);
    }

    //! An accessor
    /**
    * Fetches a query resources and stores it in a local member
    * @param $sql string the database query to run
    * @return void
    */
    function fetch($sql) {
        $this->query=mysql_unbuffered_query($sql,$this->db); // Perform query here
    }

    //! An accessor
    /**
    * Returns an associative array of a query row
    * @return mixed
    */
    function getRow () {
        if ( $row=mysql_fetch_array($this->query,MYSQL_ASSOC) )
            return $row;
        else
            return false;
    }
}
?>
在它上边放上模型。
<?php
/**
*  Fetches “products” from the database
*/
class ProductModel {
    /**
    * Private
    * $dao an instance of the DataAccess class
    */
    var $dao;

    //! A constructor.
    /**
    * Constucts a new ProductModel object
    * @param $dbobject an instance of the DataAccess class
    */
    function ProductModel (&$dao) {
        $this->dao=& $dao;
    }

    //! A manipulator
    /**
    * Tells the $dboject to store this query as a resource
    * @param $start the row to start from
    * @param $rows the number of rows to fetch
    * @return void
    */
    function listProducts($start=1,$rows=50) {
        $this->dao->fetch(“SELECT * FROM products LIMIT “.$start.”, “.$rows);
    }

    //! A manipulator
    /**
    * Tells the $dboject to store this query as a resource
    * @param $id a primary key for a row
    * @return void
    */
    function listProduct($id) {
        $this->dao->fetch(“SELECT * FROM products WHERE PRODUCTID='”.$id.”‘”);
    }

    //! A manipulator
    /**
    * Fetches a product as an associative array from the $dbobject
    * @return mixed
    */
    function getProduct() {
        if ( $product=$this->dao->getRow() )
            return $product;
        else
            return false;
    }
}
?>
有一点要注意的是,在模型和数据访问类之间,它们的交互从不会多于一行??没有多行被传送,那样会很快使程式慢下来。同样的程式对于使用模式的类,它只需要在内存中保留一行(Row)??其他的交给已保存的查询资源(query resource)??换句话说,我们让MYSQL替我们保持结果。

接下来是视图??我去掉了HTML以节省空间,你可以查看这篇文章的完整代码。
<?php
/**
*  Binds product data to HTML rendering
*/
class ProductView {
    /**
    * Private
    * $model an instance of the ProductModel class
    */
    var $model;

    /**
    * Private
    * $output rendered HTML is stored here for display
    */
    var $output;

    //! A constructor.
    /**
    * Constucts a new ProductView object
    * @param $model an instance of the ProductModel class
    */
    function ProductView (&$model) {
        $this->model=& $model;
    }

    //! A manipulator
    /**
    * Builds the top of an HTML page
    * @return void
    */
    function header () {

    }

    //! A manipulator
    /**
    * Builds the bottom of an HTML page
    * @return void
    */
    function footer () {

    }

    //! A manipulator
    /**
    * Displays a single product
    * @return void
    */
    function productItem($id=1) {
        $this->model->listProduct($id);
        while ( $product=$this->model->getProduct() ) {
             // Bind data to HTML
        }
    }

    //! A manipulator
    /**
    * Builds a product table
    * @return void
    */
    function productTable($rownum=1) {
        $rowsperpage=’20’;
        $this->model->listProducts($rownum,$rowsperpage);
        while ( $product=$this->model->getProduct() ) {
             // Bind data to HTML
        }
    }

    //! An accessor
    /**
    * Returns the rendered HTML
    * @return string
    */
    function display () {
        return $this->output;
    }
}
?>
最后是控制器,我们将把视图实现为一个子类。
<?php
/**
*  Controls the application
*/
class ProductController extends ProductView {

    //! A constructor.
    /**
    * Constucts a new ProductController object
    * @param $model an instance of the ProductModel class
    * @param $getvars the incoming HTTP GET method variables
    */
    function ProductController (&$model,$getvars=null) {
        ProductView::ProductView($model);
        $this->header();
        switch ( $getvars[‘view’] ) {
            case “product”:
                $this->productItem($getvars[‘id’]);
                break;
            default:
                if ( empty ($getvars[‘rownum’]) ) {
                    $this->productTable();
                } else {
                    $this->productTable($getvars[‘rownum’]);
                }
                break;
        }
        $this->footer();
    }
}
?>

 

 

注意这不是实现MVC的唯一方式??比如你可以用控制器实现模型同时整合视图。这只是演示模式的一种方法。

我们的index.php 文件看起来像这样:
<?php
require_once(‘lib/DataAccess.php’);
require_once(‘lib/ProductModel.php’);
require_once(‘lib/ProductView.php’);
require_once(‘lib/ProductController.php’);

$dao=& new DataAccess (‘localhost’,’user’,’pass’,’dbname’);
$productModel=& new ProductModel($dao);
$productController=& new ProductController($productModel,$_GET);
echo $productController->display();
?>
漂亮而简单。

我们有一些使用控制器的技巧,在PHP中你可以这样做:
$this->{$_GET[‘method’]}($_GET[‘param’]);
一个建议是你最好定义程序URL的名字空间形式(namespace),那样它会比较规范比如:
“index.php?class=ProductView&method=productItem&id=4”
通过它我们可以这样处理我们的控制器:
$view=new $_GET[‘class’];
$view->{$_GET[‘method’]($_GET[‘id’]);
有时候,建立控制器是件很困难的事情,比如当你在开发速度和适应性之间权衡时。一个获得灵感的好去处是Apache group 的Java Struts,它的控制器完全是由XML文档定义的。

PHP5的 SPL

PHP SPL笔记
目录
第一部分 简介
1. 什么是SPL?
2. 什么是Iterator?
第二部分 SPL Interfaces
3. Iterator界面
4. ArrayAccess界面
5. IteratorAggregate界面
6. RecursiveIterator界面
7. SeekableIterator界面
8. Countable界面
第三部分 SPL Classes
9. SPL的内置类
10. DirectoryIterator类
11. ArrayObject类
12. ArrayIterator类
13. RecursiveArrayIterator类和RecursiveIteratorIterator类
14. FilterIterator类
15. SimpleXMLIterator类
16. CachingIterator类
17. LimitIterator类
18. SplFileObject类
第一部 简介
1. 什么是SPL?
SPL是Standard PHP Library(PHP标准库)的缩写。
根据官方定义,它是“a collection of interfaces and classes that are meant to solve standard problems”。但是,目前在使用中,SPL更多地被看作是一种使object(物体)模仿array(数组)行为的interfaces和 classes。
2. 什么是Iterator?
SPL的核心概念就是Iterator。这指的是一种Design Pattern,根据《Design Patterns》一书的定义,Iterator的作用是“provide an object which traverses some aggregate structure, abstracting away assumptions about the implementation of that structure.”
wikipedia中说,”an iterator is an object which allows a programmer to traverse through all the elements of a collection, regardless of its specific implementation”.……”the iterator pattern is a design pattern in which iterators are used to access the elements of an aggregate object sequentially without exposing its underlying representation”.
通俗地说,Iterator能够使许多不同的数据结构,都能有统一的操作界面,比如一个数据库的结果集、同一个目录中的文件集、或者一个文本中每一行构成的集合。
如果按照普通情况,遍历一个MySQL的结果集,程序需要这样写:

PHP代码
// Fetch the “aggregate structure”  
$result = mysql_query(“SELECT * FROM users”);  
// Iterate over the structure  
while ( $row = mysql_fetch_array($result) ) {  
   // do stuff with the row here  
}  
读出一个目录中的内容,需要这样写:

PHP代码
// Fetch the “aggregate structure”  
$dh = opendir(‘/home/harryf/files’);  
// Iterate over the structure  
while ( $file = readdir($dh) ) {  
   // do stuff with the file here  
}  

 

读出一个文本文件的内容,需要这样写:

PHP代码
// Fetch the “aggregate structure”  
$fh = fopen(“/home/hfuecks/files/results.txt”, “r”);  
// Iterate over the structure  
while (!feof($fh)) {  
   $line = fgets($fh);  
   // do stuff with the line here  
}  
上面三段代码,虽然处理的是不同的resource(资源),但是功能都是遍历结果集(loop over contents),因此Iterator的基本思想,就是将这三种不同的操作统一起来,用同样的命令界面,处理不同的资源。
第二部分 SPL Interfaces
3. Iterator界面
SPL规定,所有部署了Iterator界面的class,都可以用在foreach Loop中。Iterator界面中包含5个必须部署的方法:
        * current()
          This method returns the current index’s value. You are solely
          responsible for tracking what the current index is as the
         interface does not do this for you.
        * key()
          This method returns the value of the current index’s key. For
          foreach loops this is extremely important so that the key
          value can be populated.
        * next()
          This method moves the internal index forward one entry.
        * rewind()
          This method should reset the internal index to the first element.
        * valid()
          This method should return true or false if there is a current
          element. It is called after rewind() or next().

下面就是一个部署了Iterator界面的class示例:

PHP代码
/** 
* An iterator for native PHP arrays, re-inventing the wheel 

* Notice the “implements Iterator” – important! 
*/  
class ArrayReloaded implements Iterator {  
   /** 
   * A native PHP array to iterate over 
   */  
 private $array = array();  
   /** 
   * A switch to keep track of the end of the array 
   */  
 private $valid = FALSE;  
   /** 
   * Constructor 
   * @param array native PHP array to iterate over 
   */  
 function __construct($array) {  
   $this->array = $array;  
 }  
   /** 
   * Return the array “pointer” to the first element 
   * PHP’s reset() returns false if the array has no elements 
   */  
 function rewind(){  
   $this->valid = (FALSE !== reset($this->array));  
 }  
   /** 
   * Return the current array element 
   */  
 function current(){  
   return current($this->array);  
 }  
   /** 
   * Return the key of the current array element 
   */  
 function key(){  
   return key($this->array);  
 }  
   /** 
   * Move forward by one 
   * PHP’s next() returns false if there are no more elements 
   */  
 function next(){  
   $this->valid = (FALSE !== next($this->array));  
 }  
   /** 
   * Is the current element valid? 
   */  
 function valid(){  
   return $this->valid;  
 }  
}  

使用方法如下:

PHP代码
// Create iterator object  
$colors = new ArrayReloaded(array (‘red’,’green’,’blue’,));  
// Iterate away!  
foreach ( $colors as $color ) {  
 echo $color.”\n”;  
}  

你也可以在foreach循环中使用key()方法:

PHP代码
// Display the keys as well  
foreach ( $colors as $key => $color ) {  
 echo “$key: $color”;  
}  

除了foreach循环外,也可以使用while循环,

PHP代码
// Reset the iterator – foreach does this automatically  
$colors->rewind();  
// Loop while valid  
while ( $colors->valid() ) {  
   echo $colors->key().”: “.$colors->current().” 
“;  
   $colors->next();  
}  

根据测试,while循环要稍快于foreach循环,因为运行时少了一层中间调用。
4. ArrayAccess界面
部署ArrayAccess界面,可以使得object像array那样操作。ArrayAccess界面包含四个必须部署的方法:
        * offsetExists($offset)
          This method is used to tell php if there is a value
          for the key specified by offset. It should return
          true or false.
        * offsetGet($offset)
          This method is used to return the value specified
          by the key offset.
        * offsetSet($offset, $value)
          This method is used to set a value within the object,
          you can throw an exception from this function for a
          read-only collection.
        * offsetUnset($offset)
          This method is used when a value is removed from
          an array either through unset() or assigning the key
          a value of null. In the case of numerical arrays, this
          offset should not be deleted and the array should
          not be reindexed unless that is specifically the
          behavior you want.

下面就是一个部署ArrayAccess界面的实例:

PHP代码
/** 
* A class that can be used like an array 
*/  
class Article implements ArrayAccess {  
 public $title;  
 public $author;  
 public $category;   
 function __construct($title,$author,$category) {  
   $this->title = $title;  
   $this->author = $author;  
   $this->category = $category;  
 }  
 /** 
 * Defined by ArrayAccess interface 
 * Set a value given it’s key e.g. $A[‘title’] = ‘foo’; 
 * @param mixed key (string or integer) 
 * @param mixed value 
 * @return void 
 */  
 function offsetSet($key, $value) {  
   if ( array_key_exists($key,get_object_vars($this)) ) {  
     $this->{$key} = $value;  
   }  
 }  
 /** 
 * Defined by ArrayAccess interface 
 * Return a value given it’s key e.g. echo $A[‘title’]; 
 * @param mixed key (string or integer) 
 * @return mixed value 
 */  
 function offsetGet($key) {  
   if ( array_key_exists($key,get_object_vars($this)) ) {  
     return $this->{$key};  
   }  
 }  
 /** 
 * Defined by ArrayAccess interface 
 * Unset a value by it’s key e.g. unset($A[‘title’]); 
 * @param mixed key (string or integer) 
 * @return void 
 */  
 function offsetUnset($key) {  
   if ( array_key_exists($key,get_object_vars($this)) ) {  
     unset($this->{$key});  
   }  
 }  
 /** 
 * Defined by ArrayAccess interface 
 * Check value exists, given it’s key e.g. isset($A[‘title’]) 
 * @param mixed key (string or integer) 
 * @return boolean 
 */  
 function offsetExists($offset) {  
   return array_key_exists($offset,get_object_vars($this));  
 }  
}  

使用方法如下:

PHP代码
// Create the object  
$A = new Article(‘SPL Rocks’,’Joe Bloggs’, ‘PHP’);  
// Check what it looks like  
echo ‘Initial State:’;  
print_r($A);  
echo “\n”;  
// Change the title using array syntax  
$A[‘title’] = ‘SPL _really_ rocks’;  
// Try setting a non existent property (ignored)  
$A[‘not found’] = 1;  
// Unset the author field  
unset($A[‘author’]);  
// Check what it looks like again  
echo ‘Final State:’;  
print_r($A);  
echo “\n”;  

运行结果如下:
    Initial State:
    Article Object
    (
       [title] => SPL Rocks
       [author] => Joe Bloggs
       [category] => PHP
    )
    Final State:
    Article Object
    (
       [title] => SPL _really_ rocks
       [category] => PHP
    )

可以看到,$A虽然是一个object,但是完全可以像array那样操作。
你还可以在读取数据时,增加程序内部的逻辑:

PHP代码
function offsetGet($key) {  
   if ( array_key_exists($key,get_object_vars($this)) ) {  
     return strtolower($this->{$key});  
   }  
 }  

5. IteratorAggregate界面
但是,虽然$A可以像数组那样操作,却无法使用foreach遍历,除非部署了前面提到的Iterator界面。
另一个解决方法是,有时会需要将数据和遍历部分分开,这时就可以部署IteratorAggregate界面。它规定了一个getIterator()方法,返回一个使用Iterator界面的object。
还是以上一节的Article类为例:

PHP代码
class Article implements ArrayAccess, IteratorAggregate {  
/** 
 * Defined by IteratorAggregate interface 
 * Returns an iterator for for this object, for use with foreach 
 * @return ArrayIterator 
 */  
 function getIterator() {  
   return new ArrayIterator($this);  
 }  

 

使用方法如下:

PHP代码
$A = new Article(‘SPL Rocks’,’Joe Bloggs’, ‘PHP’);  
// Loop (getIterator will be called automatically)  
echo ‘Looping with foreach:’;  
foreach ( $A as $field => $value ) {  
 echo “$field : $value”;  
}  
echo ”;  
// Get the size of the iterator (see how many properties are left)  
echo “Object has “.sizeof($A->getIterator()).” elements”;  

显示结果如下:
    Looping with foreach:
    title : SPL Rocks
    author : Joe Bloggs
    category : PHP
    Object has 3 elements

6. RecursiveIterator界面
这个界面用于遍历多层数据,它继承了Iterator界面,因而也具有标准的current()、key()、next()、 rewind()和valid()方法。同时,它自己还规定了getChildren()和hasChildren()方法。The getChildren() method must return an object that implements RecursiveIterator.
7. SeekableIterator界面
SeekableIterator界面也是Iterator界面的延伸,除了Iterator的5个方法以外,还规定了seek()方法,参数是元素的位置,返回该元素。如果该位置不存在,则抛出OutOfBoundsException。
下面是一个是实例:

PHP代码
class PartyMemberIterator implements SeekableIterator  
{  
    public function __construct(PartyMember $member)  
    {  
        // Store $member locally for iteration  
    }  
    public function seek($index)  
    {  
        $this->rewind();  
        $position = 0;  
        while ($position < $index && $this->valid()) {  
            $this->next();  
            $position++;  
        }  
        if (!$this->valid()) {  
            throw new OutOfBoundsException(‘Invalid position’);  
        }  
    }  
    // Implement current(), key(), next(), rewind()  
    // and valid() to iterate over data in $member  
}  

8. Countable界面
这个界面规定了一个count()方法,返回结果集的数量。
第三部分 SPL Classes
9. SPL的内置类
SPL除了定义一系列Interfaces以外,还提供一系列的内置类,它们对应不同的任务,大大简化了编程。
查看所有的内置类,可以使用下面的代码:

PHP代码
// a simple foreach() to traverse the SPL class names  
foreach(spl_classes() as $key=>$value)  
{  
    echo $key.’ -> ‘.$value.”;  
}  

10. DirectoryIterator类
这个类用来查看一个目录中的所有文件和子目录:
 

PHP代码
try{  
  /*** class create new DirectoryIterator Object ***/  
    foreach ( new DirectoryIterator(‘./’) as $Item )  
        {  
        echo $Item.”;  
        }  
    }  
/*** if an exception is thrown, catch it here ***/  
catch(Exception $e){  
    echo ‘No files Found!’;  
}  
查看文件的详细信息:
 

PHP代码
foreach(new DirectoryIterator(‘./’ ) as $file )  
    {  
    if( $file->getFilename()  == ‘foo.txt’ )  
        {  
        echo ‘ getFilename() ‘; var_dump($file->getFilename()); echo ‘ ‘;  
    echo ‘ getBasename() ‘; var_dump($file->getBasename()); echo ‘ ‘;  
        echo ‘ isDot() ‘; var_dump($file->isDot()); echo ‘ ‘;  
        echo ‘ __toString() ‘; var_dump($file->__toString()); echo ‘ ‘;  
        echo ‘ getPath() ‘; var_dump($file->getPath()); echo ‘ ‘;  
        echo ‘ getPathname() ‘; var_dump($file->getPathname()); echo ‘ ‘;  
        echo ‘ getPerms() ‘; var_dump($file->getPerms()); echo ‘ ‘;  
        echo ‘ getInode() ‘; var_dump($file->getInode()); echo ‘ ‘;  
        echo ‘ getSize() ‘; var_dump($file->getSize()); echo ‘ ‘;  
        echo ‘ getOwner() ‘; var_dump($file->getOwner()); echo ‘ ‘;  
        echo ‘ $file->getGroup() ‘; var_dump($file->getGroup()); echo ‘ ‘;  
        echo ‘ getATime() ‘; var_dump($file->getATime()); echo ‘ ‘;  
        echo ‘ getMTime() ‘; var_dump($file->getMTime()); echo ‘ ‘;  
        echo ‘ getCTime() ‘; var_dump($file->getCTime()); echo ‘ ‘;  
        echo ‘ getType() ‘; var_dump($file->getType()); echo ‘ ‘;  
        echo ‘ isWritable() ‘; var_dump($file->isWritable()); echo ‘ ‘;  
        echo ‘ isReadable() ‘; var_dump($file->isReadable()); echo ‘ ‘;  
        echo ‘ isExecutable( ‘; var_dump($file->isExecutable()); echo ‘ ‘;  
        echo ‘ isFile() ‘; var_dump($file->isFile()); echo ‘ ‘;  
        echo ‘ isDir() ‘; var_dump($file->isDir()); echo ‘ ‘;  
        echo ‘ isLink() ‘; var_dump($file->isLink()); echo ‘ ‘;  
        echo ‘ getFileInfo() ‘; var_dump($file->getFileInfo()); echo ‘ ‘;  
        echo ‘ getPathInfo() ‘; var_dump($file->getPathInfo()); echo ‘ ‘;  
        echo ‘ openFile() ‘; var_dump($file->openFile()); echo ‘ ‘;  
        echo ‘ setFileClass() ‘; var_dump($file->setFileClass()); echo ‘ ‘;  
        echo ‘ setInfoClass() ‘; var_dump($file->setInfoClass()); echo ‘ ‘;  
        }  
}  
除了foreach循环外,还可以使用while循环:

PHP代码
    /*** create a new iterator object ***/  
    $it = new DirectoryIterator(‘./’);  
    /*** loop directly over the object ***/  
    while($it->valid())  
    {  
        echo $it->key().’ — ‘.$it->current().’ ‘;  
        /*** move to the next iteration ***/  
        $it->next();  
    }  

如果要过滤所有子目录,可以在valid()方法中过滤:

PHP代码
/*** create a new iterator object ***/  
$it = new DirectoryIterator(‘./’);  
/*** loop directly over the object ***/  
while($it->valid())  
{  
    /*** check if value is a directory ***/  
    if($it->isDir())  
    {  
       /*** echo the key and current value ***/  
       echo $it->key().’ — ‘.$it->current().”;  
    }  
    /*** move to the next iteration ***/  
    $it->next();  
 }  

11. ArrayObject类
这个类可以将Array转化为object。
 

PHP代码
/*** a simple array ***/  
$array = array(‘koala’, ‘kangaroo’, ‘wombat’, ‘wallaby’, ’emu’, ‘kiwi’, ‘kookaburra’, ‘platypus’);  
/*** create the array object ***/  
$arrayObj = new ArrayObject($array);  
/*** iterate over the array ***/  
for($iterator = $arrayObj->getIterator();  
   /*** check if valid ***/  
   $iterator->valid();  
   /*** move to the next array member ***/  
   $iterator->next())  
    {  
    /*** output the key and current array value ***/  
    echo $iterator->key() . ‘ => ‘ . $iterator->current() . ”;  
    }  
增加一个元素:
    $arrayObj->append(‘dingo’);

对元素排序:
    $arrayObj->natcasesort();

显示元素的数量:
    echo $arrayObj->count();

删除一个元素:
    $arrayObj->offsetUnset(5);

某一个元素是否存在:
     if ($arrayObj->offsetExists(3))
        {
           echo ‘Offset Exists’;
        }

更改某个位置的元素值:
     $arrayObj->offsetSet(5, “galah”);

显示某个位置的元素值:
    echo $arrayObj->offsetGet(4);

12. ArrayIterator类
这个类实际上是对ArrayObject类的补充,为后者提供遍历功能。
示例如下:
 

PHP代码
/*** a simple array ***/  
$array = array(‘koala’, ‘kangaroo’, ‘wombat’, ‘wallaby’, ’emu’, ‘kiwi’, ‘kookaburra’, ‘platypus’);  
try {  
    $object = new ArrayIterator($array);  
    foreach($object as $key=>$value)  
    {  
        echo $key.’ => ‘.$value.”;  
    }  
}  
catch (Exception $e)  
{  
    echo $e->getMessage();  
}  
  
//rayIterator类也支持offset类方法和count()方法:  
  
    /*** a simple array ***/  
$array = array(‘koala’, ‘kangaroo’, ‘wombat’, ‘wallaby’, ’emu’, ‘kiwi’, ‘kookaburra’, ‘platypus’);  
try {  
    $object = new ArrayIterator($array);  
    /*** check for the existence of the offset 2 ***/  
    if($object->offSetExists(2))  
    {  
        /*** set the offset of 2 to a new value ***/  
        $object->offSetSet(2, ‘Goanna’);  
    }  
   /*** unset the kiwi ***/  
   foreach($object as $key=>$value)  
   {  
        /*** check the value of the key ***/  
        if($object->offSetGet($key) === ‘kiwi’)  
        {  
            /*** unset the current key ***/  
            $object->offSetUnset($key);  
        }  
        echo ”.$key.’ – ‘.$value.”.”\n”;  
    }  
}  
catch (Exception $e)  
{  
    echo $e->getMessage();  
}  
    ?>
   

13. RecursiveArrayIterator类和RecursiveIteratorIterator类
ArrayIterator类和ArrayObject类,只支持遍历一维数组。如果要遍历多维数组,必须先用 RecursiveIteratorIterator生成一个Iterator,然后再对这个Iterator使用 RecursiveIteratorIterator。

PHP代码
$array = array(  
   array(‘name’=>’butch’, ‘sex’=>’m’, ‘breed’=>’boxer’),  
   array(‘name’=>’fido’, ‘sex’=>’m’, ‘breed’=>’doberman’),  
   array(‘name’=>’girly’,’sex’=>’f’, ‘breed’=>’poodle’)  
);  
foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $key=>$value)  
{  
    echo $key.’ — ‘.$value.”;  
}  

14. FilterIterator类
FilterIterator类可以对元素进行过滤,只要在accept()方法中设置过滤条件就可以了。
示例如下:

PHP代码
        /*** a simple array ***/  
    $animals = array(‘koala’, ‘kangaroo’, ‘wombat’, ‘wallaby’, ’emu’, ‘NZ’=>’kiwi’, ‘kookaburra’, ‘platypus’);  
    class CullingIterator extends FilterIterator{  
    /*** The filteriterator takes  a iterator as param: ***/  
    public function __construct( Iterator $it ){  
      parent::__construct( $it );  
    }  
    /*** check if key is numeric ***/  
    function accept(){  
      return is_numeric($this->key());  
    }  
    }/*** end of class ***/  
    $cull = new CullingIterator(new ArrayIterator($animals));  
    foreach($cull as $key=>$value)  
        {  
        echo $key.’ == ‘.$value.”;  
        }  
    ?>  
//下面是另一个返回质数的例子:  
     
    class PrimeFilter extends FilterIterator{  
    /*** The filteriterator takes  a iterator as param: ***/  
    public function __construct(Iterator $it){  
      parent::__construct($it);  
    }  
    /*** check if current value is prime ***/  
    function accept(){  
    if($this->current() % 2 != 1)  
        {  
        return false;  
        }  
    $d = 3;  
    $x = sqrt($this->current());  
    while ($this->current() % $d != 0 && $d < $x)  
        {  
        $d += 2;  
        }  
     return (($this->current() % $d == 0 && $this->current() != $d) * 1) == 0 ? true : false;  
    }  
    }/*** end of class ***/  
    /*** an array of numbers ***/  
    $numbers = range(212345,212456);  
    /*** create a new FilterIterator object ***/  
    $primes = new primeFilter(new ArrayIterator($numbers));  
    foreach($primes as $value)  
        {  
        echo $value.’ is prime.’;  
        }  

15. SimpleXMLIterator类
这个类用来遍历xml文件。
示例如下:
 原文的XML在就是变型的,或者说在解释的时候已经坏掉了,所以。我删除了,直接看方法吧:by 膘叔

PHP代码
/*** a new simpleXML iterator object ***/  
try    {  
       /*** a new simple xml iterator ***/  
       $it = new SimpleXMLIterator($xmlstring);  
       /*** a new limitIterator object ***/  
       foreach(new RecursiveIteratorIterator($it,1) as $name => $data)  
          {  
          echo $name.’ — ‘.$data.”;  
          }  
    }  
catch(Exception $e)  
    {  
    echo $e->getMessage();  
    }  

new RecursiveIteratorIterator($it,1)表示显示所有包括父元素在内的子元素。
显示某一个特定的元素值,可以这样写:

PHP代码
try {  
/*** a new simpleXML iterator object ***/  
$sxi =  new SimpleXMLIterator($xmlstring); 

foreach ( $sxi as $node )  
    {  
    foreach($node as $k=>$v)  
        {  
        echo $v->species.”;  
        }  
    }  
}  
catch(Exception $e)  
{  
echo $e->getMessage();  
}  
相对应的while循环写法为:
 

PHP代码
try {  
$sxe = simplexml_load_string($xmlstring, ‘SimpleXMLIterator’);  
for ($sxe->rewind(); $sxe->valid(); $sxe->next())  
    {  
    if($sxe->hasChildren())  
        {  
        foreach($sxe->getChildren() as $element=>$value)  
          {  
          echo $value->species.”;  
          }  
        }  
     }  
   }  
catch(Exception $e)  
   {  
   echo $e->getMessage();  
   }  
最方便的写法,还是使用xpath:
 

PHP代码
try {  
 /*** a new simpleXML iterator object ***/  
 $sxi =  new SimpleXMLIterator($xmlstring);  
 /*** set the xpath ***/  
 $foo = $sxi->xpath(‘animal/category/species’);  
 /*** iterate over the xpath ***/  
 foreach ($foo as $k=>$v)  
     {  
     echo $v.”;  
     }  
 }  
ch(Exception $e)  
 {  
 echo $e->getMessage();  
 }  
下面的例子,显示有namespace的情况:

PHP代码
/*** a new simpleXML iterator object ***/  
try {  
    /*** a new simpleXML iterator object ***/  
    $sxi =  new SimpleXMLIterator($xmlstring);  
    $sxi-> registerXPathNamespace(‘spec’, ‘http://www.exampe.org/species-title’);  
    /*** set the xpath ***/  
    $result = $sxi->xpath(‘//spec:name’);  
    /*** get all declared namespaces ***/  
   foreach($sxi->getDocNamespaces(‘animal’) as $ns)  
        {  
        echo $ns.”;  
        }  
    /*** iterate over the xpath ***/  
    foreach ($result as $k=>$v)  
        {  
        echo $v.”;  
        }  
    }  
catch(Exception $e)  
    {  
    echo $e->getMessage();  
    }  
增加一个节点:

PHP代码
try {  
    /*** a new simpleXML iterator object ***/  
    $sxi =  new SimpleXMLIterator($xmlstring);  
    /*** add a child ***/  
    $sxi->addChild(‘animal’, ‘Tiger’);  
    /*** a new simpleXML iterator object ***/  
    $new = new SimpleXmlIterator($sxi->saveXML());  
    /*** iterate over the new tree ***/  
    foreach($new as $val)  
        {  
        echo $val.”;  
        }  
    }  
catch(Exception $e)  
    {  
    echo $e->getMessage();  
    }  

增加属性:

PHP代码
try {  
    /*** a new simpleXML iterator object ***/  
    $sxi =  new SimpleXMLIterator($xmlstring);  
    /*** add an attribute with a namespace ***/  
    $sxi->addAttribute(‘id:att1’, ‘good things’, ‘urn::test-foo’);  
    /*** add an attribute without a  namespace ***/  
    $sxi->addAttribute(‘att2’, ‘no-ns’);  
    echo htmlentities($sxi->saveXML());  
    }  
catch(Exception $e)  
    {  
    echo $e->getMessage();  
    }  

16. CachingIterator类
这个类有一个hasNext()方法,用来判断是否还有下一个元素。
示例如下:
 

PHP代码
   /*** a simple array ***/  
$array = array(‘koala’, ‘kangaroo’, ‘wombat’, ‘wallaby’, ’emu’, ‘kiwi’, ‘kookaburra’, ‘platypus’);  
try {  
    /*** create a new object ***/  
    $object = new CachingIterator(new ArrayIterator($array));  
    foreach($object as $value)  
        {  
        echo $value;  
        if($object->hasNext())  
            {  
            echo ‘,’;  
            }  
        }  
    }  
catch (Exception $e)  
    {  
    echo $e->getMessage();  
    }  

17. LimitIterator类
这个类用来限定返回结果集的数量和位置,必须提供offset和limit两个参数,与SQL命令中limit语句类似。
示例如下:

PHP代码
    /*** the offset value ***/  
$offset = 3;  
/*** the limit of records to show ***/  
$limit = 2;  
$array = array(‘koala’, ‘kangaroo’, ‘wombat’, ‘wallaby’, ’emu’, ‘kiwi’, ‘kookaburra’, ‘platypus’);  
$it = new LimitIterator(new ArrayIterator($array), $offset, $limit);  
foreach($it as $k=>$v)  
    {  
    echo $it->getPosition().”;  
    }  

另一个例子是:
  

PHP代码
/*** a simple array ***/  
$array = array(‘koala’, ‘kangaroo’, ‘wombat’, ‘wallaby’, ’emu’, ‘kiwi’, ‘kookaburra’, ‘platypus’);  
$it = new LimitIterator(new ArrayIterator($array));  
try  
    {  
    $it->seek(5);  
    echo $it->current();  
    }  
catch(OutOfBoundsException $e)  
    {  
    echo $e->getMessage() . “”;  
    }  
18. SplFileObject类
这个类用来对文本文件进行遍历。
示例如下:

PHP代码
try{  
    // iterate directly over the object  
    foreach( new SplFileObject(“/usr/local/apache/logs/access_log”) as $line)  
    // and echo each line of the file  
    echo $line.”;  
}  
catch (Exception $e)  
    {  
    echo $e->getMessage();  
    }  

返回文本文件的第三行,可以这样写:

PHP代码
try{  
    $file = new SplFileObject(“/usr/local/apache/logs/access_log”);  
    $file->seek(3);  
    echo $file->current();  
}  
catch (Exception $e)  
{  
    echo $e->getMessage();  
}  
[参考文献]
1. Introduction to Standard PHP Library (SPL), By Kevin Waterson
2. Introducing PHP 5’s Standard Library, By Harry Fuecks
3. The Standard PHP Library (SPL), By Ben Ramsey
4. SPL – Standard PHP Library Documentation