什么是SPL?
SPL是Standard PHP Library的缩写,属于PHP标准库的一支,是PHP5最新增加的功能,用来解决一些PHP语言本身不支持的问题以及实现更有效的数据的操作。据说是由某个很牛的大师因为不满于传统的PHP的对象的操作,而自己开发的一套库,后来被引入到PHP标准库当中。SPL能做很多事,以下就是一个很好的例子。
让对象像数组一样赋值、读取、删除
我想你一定听过PHP5中的魔术方法,那么数组方式的对象操作肯定不会陌生了。如果一个对象通过实现一个接口(也可以说是继承),那么它也会具有数组的操作方式,当然,你需要定义自己的魔术方法了。
<?php
/**
* 测试接口的使用
*
* @author monkee
* @since 2011-08-15
*/
class arrayTest implements ArrayAccess
{
private $d = array();
function offsetExists($offset){
echo __METHOD__."\n";
return array_key_exists($offset, $this->d);
}
function offsetGet($offset){
echo __METHOD__."\n";
return $this->d[$offset];
}
function offsetSet($offset, $value){
echo __METHOD__."\n";
$this->d[$offset] = $value;
}
function offsetUnset($offset){
echo __METHOD__."\n";
unset($this->d[$offset]);
return true;
}
}
$t = new arrayTest();
isset($t['m']);
$t['m'] = 123456;
$m = $t['m'];
unset($t['m']);
?>
看看上面的代码能够让你得到什么?是不是很惊讶,对象arrayTest竟然可以拥有像对数组一样的操作方式。那么现在,如果你需要设计出能够使程序员方便使用的框架来,那么我想这样的方式也是你会考虑的一种选择之一。
Interface ArrayAccess
这个接口是SPL中的一个接口,它定义如下:
interface ArrayAccess {
function offsetExists($key); //被isset调用时
function offsetGet($key); //被当作数组读时
function offsetSet($key, $value); //被当作数组赋值时
function offsetUnset($key); //被当作数组unset时
}
需要拥有数组操作方式的类,需要对其进行继承(我喜欢这么来描述)
class arrayTest implements ArrayAccess
那么你就拥有了类的数组方式的操作。
Interface Iterator
现在我们只是拥有了对数组类的赋值和取值,然而我们对foreach这样的对于数组很方便的操作还没有使用。如果要支持指针类的操作,那么:
<?php
/**
* 测试接口的使用
*
* @author monkee
* @since 2011-08-15
*/
class arrayTest implements Iterator
{
protected $d = array('1', '2', '3');
protected $currIndex = 0;
protected $all = 0;
protected $more = false;
function __construct($array){
if(!is_array($array)){
//do some error thing
trigger_error('Error params' , E_USER_WARNING);
}
$this->d = $array;
$this->currIndex = 0;
$this->all = count($this->d);
$this->more = ($this->all > 0);
}
function rewind(){
echo __METHOD__."\n";
}
function valid(){
echo __METHOD__."\n";
return $this->more;
}
function key(){
echo __METHOD__."\n";
return key($this->d);
}
function current(){
echo __METHOD__."\n";
return current($this->d);
}
function next(){
echo __METHOD__."\n";
$v = next($this->d);
$this->currIndex++;
$this->more = ($this->currIndex < $this->all);
}
}
$t = new arrayTest(array('a' => 'A', 'b' => 'B', 'c' => 'C'));
foreach($t as $key => $item){
echo "{$key} => {$item} \n";
}
?>
上面的例子可以通过,也可以正常使用。
其中,Iterator的定义如下:
Iterator implements Traversable {
abstract public mixed current ( void ); //返回当前的数据
abstract public scalar key ( void ); //返回当前的KEY值
abstract public void next ( void ); //下一个指针
abstract public void rewind ( void ); //建立指针时触发,在foreach的开始部分
abstract public boolean valid ( void ); //当前指针是否有效
}
完美的数组类
如果集合了如上两条功能,那么我们的类便更接近于数组的操作了。
<?php
/**
* 测试接口的使用
*
* @author monkee
* @since 2011-08-15
*/
class arrayTest implements ArrayAccess, Iterator
{
protected $d = array('1', '2', '3');
protected $currIndex = 0;
protected $all = 0;
protected $more = false;
function __construct($array){
if(!is_array($array)){
//do some error thing
trigger_error('Error params' , E_USER_WARNING);
}
$this->d = $array;
$this->currIndex = 0;
$this->all = count($this->d);
$this->more = ($this->all > 0);
}
function offsetExists($offset){
echo __METHOD__."\n";
return array_key_exists($offset, $this->d);
}
function offsetGet($offset){
echo __METHOD__."\n";
return $this->d[$offset];
}
function offsetSet($offset, $value){
echo __METHOD__."\n";
$this->d[$offset] = $value;
}
function offsetUnset($offset){
echo __METHOD__."\n";
unset($this->d[$offset]);
return true;
}
function rewind(){
echo __METHOD__."\n";
}
function valid(){
echo __METHOD__."\n";
return $this->more;
}
function key(){
echo __METHOD__."\n";
return key($this->d);
}
function current(){
echo __METHOD__."\n";
return current($this->d);
}
function next(){
echo __METHOD__."\n";
$v = next($this->d);
$this->currIndex++;
$this->more = ($this->currIndex < $this->all);
}
}
$t = new arrayTest(array('a' => 'A', 'b' => 'B', 'c' => 'C'));
echo $t['a'];
foreach($t as $key => $item){
echo "{$key} => {$item} \n";
}
?>
总结
这些功能在平常的开发中可能用不到,因为它不符合PHP标准。然而,如果在我们需要设计的框架中,希望用到类似的功能的话,那么以上的技巧便是可以考虑使用的。