04月13, 2017

SPL标准库——数组实现

SPL标准库定义

SPL是Standard PHP Library(php标准库)的缩写。SPL对PHP引擎进行了扩展,它实现了一组接口,利用它,我们可以轻松地利用对象实现各种数据结构。另外,SPL还内置了一些函数实现诸如自动加载等功能。

利用SPL实现对象的数组化操作

使对象能够像数组一样操作,只需要让对象实现ArrayAccess接口即可。

ArrayAccess接口如下

interface ArrayAccess {
    //检查一个偏移位置是否存在 
    public mixed offsetExists ( mixed $offset  );

    //获取一个偏移位置的值 
    public mixed offsetGet( mixed $offset  );

    //设置一个偏移位置的值 
    public mixed offsetSet ( mixed $offset  );

    //复位一个偏移位置的值 
    public mixed offsetUnset  ( mixed $offset  );
}

我们下面模拟一下实现,利用类实现ArrayAccess接口来操作一个User数据对象类

<?php

class MyArray implements ArrayAccess {

    private static $_instance = null;

    private $userObj = null;

    protected function __construct($userObj)
    {
        $this->userObj = $userObj;
    }

    public static function getInstance($userObj)
    {
        if (is_null ( self::$_instance ) || isset ( self::$_instance )) {
            self::$_instance = new self ($userObj);
        }
        return self::$_instance;
    }

    //检查一个偏移位置是否存在
    public function offsetExists ($name) {
        if (!empty($this->userObj->getUser($name))) return true;
        else return false;
    }

        //获取一个偏移位置的值
    public function offsetGet($name) {
        return $this->userObj->getUser($name);
    }

        //设置一个偏移位置的值
    public function offsetSet($name,$info) {
        return $this->userObj->setUser($name, $info);
    }

        //复位一个偏移位置的值
    public function offsetUnset($name ) {
        return $this->userObj->deleteUser($name);
    }
}
//User数据对象类
class userModel {

    private static $testUsers;

    public function __construct($users)
    {
        self::$testUsers = $users;
    }

    public function getUser ($name) {
        if (array_key_exists($name, self::$testUsers))
            return self::$testUsers[$name];
        else
            return [];
    }

    public function setUser ($name, $info) {
        self::$testUsers[$name] = $info;
    }

    public function deleteUser ($name) {
        unset(self::$testUsers[$name]);
    }

}
//测试代码
require_once "vendor/autoload.php";

use PHPUnit\Framework\TestCase;

class testMyArray extends TestCase {

    public function testArray ()
    {
        $testUsers =  [
            'kevin' => ['name' => 'kevin', 'age' => 38, 'hobby' => "fishing"],
            '2egg' =>  ['name' => '2egg' , 'age' => 46, 'hobby' => 'watching movie'],
        ];

        $userModel = new userModel($testUsers);

        $myArray = MyArray::getInstance($userModel);

        $this->assertEquals($testUsers['kevin'], $myArray['kevin']);

        $myArray['dog'] = ['name' => 'dog' , 'age' => 6, 'hobby' => 'eating boom'];

        $this->assertEquals(['name' => 'dog' , 'age' => 6, 'hobby' => 'eating boom'], $myArray['dog']);

    }

}

上面的代码实现了一个MyArray类,使得MyArray对象可以像数组一样赋值取值,但是我们还无法像数组一样foreach,如果想使用foreach功能,那么需要让对象实现Iterator 迭代器接口,接口如下。

interface Iterator extends Traversable{
    //返回当前元素
    public mixed current ( void );

    //返回当前元素的键
    public scalar key ( void );

    //向前移动到下一个元素
    public void next ( void );

    //返回到迭代器的第一个元素
    public void rewind ( void );

    //检查当前位置是否有效
    public boolean valid ( void );
}

还可以实现Countable接口使数组能够使用count函数

Countable {
    /* 方法 */
    abstract public int count ( void )
}

我们可以利用以上的接口实现更多复杂的数据结构

本文链接:http://www.qiana.info/post/spl_array.html

-- EOF --

Comments