PHP SPL标准库-接口

PHP SPL标准库有一下接口:

  • Countable
  • OuterIterator 
  • RecursiveIterator 
  • SeekableIterator
  • SplObserver 
  • SplSubject
  • ArrayObject

其中OuterIterator、RecursiveIterator、SeekableIterator都是继承Iterator类的。

Coutable接口:

实现Coutable接口的对象可用于 count() 函数计数。

class Mycount implements Countable
{
    public function count()
    {
        static $count = 0;
        $count++;
        return $count;
    }
}
 
$count = new Mycount();
$count->count();
$count->count();
 
echo count($count); //3
echo count($count); //4

说明:

调用 count() 函数时,Mycount::count() 方法被调用,count() 函数的第二个参数将不会产生影响。

OuterIterator接口:

它是自定义或修改迭代过程。

// IteratorIterator是OuterIterator的一个实现类
class MyOuterIterator extends  IteratorIterator {
    public function current()
    {
        return parent::current() . 'TEST';
    }
}
 
foreach(new MyOuterIterator(new ArrayIterator(['b','a','c'])) as $key => $value) {
    echo "$key->$value".PHP_EOL;
}

/*
结果:
0->bTEST
1->aTEST
2->cTEST
*/

在实际应用中,OuterIterator非常有用:

$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'mckee');
$db->query('set names utf8');
$pdoStatement = $db->query('SELECT * FROM test1', PDO::FETCH_ASSOC);
$iterator = new IteratorIterator($pdoStatement);
$tenRecordArray = iterator_to_array($iterator);
print_r($tenRecordArray);

RecursiveIterator接口:

用于循环迭代多层结构的数据,RecursiveIterator另外提供了两个方法:

RecursiveIterator::getChildren:获取当前元素下子迭代器

RecursiveIterator::hasChildren:判断当前元素下是否有迭代器

class MyRecursiveIterator implements RecursiveIterator
{
    private $_data;
    private $_position = 0;
 
    public function __construct(array $data) {
        $this->_data = $data;
    }
 
    public function valid() {
        return isset($this->_data[$this->_position]);
    }
 
    public function hasChildren() {
        return is_array($this->_data[$this->_position]);
    }
 
    public function next() {
        $this->_position++;
    }
 
    public function current() {
        return $this->_data[$this->_position];
    }
 
    public function getChildren() {
        print_r($this->_data[$this->_position]);
    }
 
    public function rewind() {
        $this->_position = 0;
    }
 
    public function key() {
        return $this->_position;
    }
}
 
$arr = array(0, 1=> array(10, 20), 2, 3 => array(1, 2));
$mri = new MyRecursiveIterator($arr);
 
foreach ($mri as $c => $v) {
    if ($mri->hasChildren()) {
        echo "$c has children: " .PHP_EOL;
        $mri->getChildren();
    } else {
        echo "$v" .PHP_EOL;
    }
}

输出结果:

0
1 has children:
Array
(
    [0] => 10
    [1] => 20
)
2
3 has children:
Array
(
    [0] => 1
    [1] => 2
)

SeekableIterator接口:

通过 seek() 方法实现可搜索的迭代器,用于搜索某个位置下的元素。

class  MySeekableIterator  implements  SeekableIterator  {
    private  $position = 0;

    private  $array  = array(
        "first element" ,
        "second element" ,
        "third element" ,
        "fourth element"
    );

    public function  seek ( $position ) {
        if (!isset( $this -> array [ $position ])) {
            throw new  OutOfBoundsException ( "invalid seek position ( $position )" );
        }
 
       $this -> position  =  $position ;
    }
 
    public function  rewind () {
        $this -> position  =  0 ;
    }
 
    public function  current () {
        return  $this -> array [ $this -> position ];
    }
 
    public function  key () {
        return  $this -> position ;
    }
 
    public function  next () {
        ++ $this -> position ;
    }
 
    public function  valid () {
        return isset( $this -> array [ $this -> position ]);
    }
}
 
try{
    $it  = new  MySeekableIterator ;
    echo  $it -> current (),  "\n" ;
 
    $it -> seek ( 2 );
    echo  $it -> current (),  "\n" ;
 
    $it -> seek ( 1 );
    echo  $it -> current (),  "\n" ;
 
    $it -> seek ( 10 );
}catch( OutOfBoundsException $e ){
    echo  $e -> getMessage ();
}

输出结果:

first element
third element
second element
invalid seek position ( 10 )

SplObserver和SplSubject接口:

SplObserver和SplSubject接口用来实现观察者设计模式,观察者设计模式是指当一个类的状态发生变化时,依赖它的对象都会收到通知并更新。使用场景非常广泛,比如说当一个事件发生后,需要更新多个逻辑操作,传统方式是在事件添加后编写逻辑,这种代码耦合并难以维护,观察者模式可实现低耦合的通知和更新机制。

SplObserver和SplSubject的接口结构:

// SplSubject结构 被观察的对象
interface SplSubject{
    public function attach(SplObserver $observer); // 添加观察者
    public function detach(SplObserver $observer); // 剔除观察者
    public function notify(); // 通知观察者
}
 
// SplObserver结构 代表观察者
interface SplObserver{
    public function update(SplSubject $subject); // 更新操作
}

看下面一个实现观察者的例子:

class Subject implements SplSubject
{
    private $observers = array();
 
    public function attach(SplObserver  $observer)
    {
        $this->observers[] = $observer;
    }
 
    public function detach(SplObserver  $observer)
    {
        if($index = array_search($observer, $this->observers, true)) {
            unset($this->observers[$index]);
        }
    }
 
    public function notify()
    {
        foreach($this->observers as $observer) {
            $observer->update($this);
        }
    }
}

class Observer1 implements  SplObserver
{
    public function update(SplSubject  $subject)
    {
        echo "逻辑1代码".PHP_EOL;
    }
}

class Observer2 implements  SplObserver
{
    public function update(SplSubject  $subject)
    {
        echo "逻辑2代码".PHP_EOL;
    }
}

$subject = new Subject();
$subject->attach(new Observer1());
$subject->attach(new Observer2());

$subject->notify();

运行结果:

逻辑1代码
逻辑2代码

ArrayObject接口:

ArrayObject 是将数组转换为数组对象。

// 返回当前数组元素
ArrayIterator::current( void )

// 返回当前数组key
ArrayIterator::key(void)

// 指向下个数组元素
ArrayIterator::next (void)

// 重置数组指针到头
ArrayIterator::rewind(void )

// 查找数组中某一位置
ArrayIterator::seek()

// 检查数组是否还包含其他元素
ArrayIterator::valid()

// 添加新元素
ArrayObject::append()

// 构造一个新的数组对象
ArrayObject::__construct()

// 返回迭代器中元素个数
ArrayObject::count()

// 从一个数组对象构造一个新迭代器
ArrayObject::getIterator()

// 判断提交的值是否存在
ArrayObject::offsetExists(mixed index )

// 指定 name 获取值
ArrayObject::offsetGet()

// 修改指定 name 的值
ArrayObject::offsetSet()

// 删除数据
ArrayObject::offsetUnset()

实现例子1:

$array =array('1'=>'one', '2'=>'two', '3'=>'three');
// 构造一个ArrayObject对象
$arrayobject = new ArrayObject($array);
for( $iterator= $arrayobject->getIterator();// 构造一个迭代器    
	$iterator->valid();  // 检查是否还含有元素    
	$iterator->next() ){ // 指向下个元素    
	echo $iterator->key() . ' => ' . $iterator->current() . "\n"; // 打印数组元素
}

输出结果:

1 => one 2 => two 3 => three

实现例子2:

$arrayobject =new ArrayObject();
$arrayobject[] = 'zero';
$arrayobject[] = 'one';
$arrayobject[] = 'two';
$iterator= $arrayobject->getIterator();
$iterator->next();
echo $iterator->key()."<br>";
// 重置指针到头部
$iterator->rewind();
echo $iterator->key();

输出结果:

1
0

 

posted @ 2019-03-20 14:18  让我们荡起双桨!  阅读(454)  评论(0编辑  收藏  举报