zoukankan      html  css  js  c++  java
  • 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 (),  "
    " ;
     
        $it -> seek ( 2 );
        echo  $it -> current (),  "
    " ;
     
        $it -> seek ( 1 );
        echo  $it -> current (),  "
    " ;
     
        $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() . "
    "; // 打印数组元素
    }
    

    输出结果:

    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
    
  • 相关阅读:
    vscode识别预览markdown文件
    工具:静态资源服务器server
    vscode配置easy sass 生成压缩和未压缩的css文件
    cocos Create简单记录
    小程序AR云识别
    小程序被冻结 解冻方法
    vscode设置px转换为rem
    js 打印文本
    .net 启动进程并执行某方法
    c# 创建文件夹、压缩成zip格式并下载
  • 原文地址:https://www.cnblogs.com/xi-jie/p/10564663.html
Copyright © 2011-2022 走看看