PHP预定义接口之 ArrayAccess
2016-02-29 19:16
761 查看
最近这段时间回家过年了,博客也没有更新,感觉少学习了好多东西,也错失了好多的学习机会,就像大家在春节抢红包时常说的一句话:一不留神错过了好几亿。废话少说,这篇博客给大家说说关于PHP预定义接口中常用到的重量级人物: ArrayAccess。大家也许会问,最基本、最常用的预定义接口有6个呢,为啥非得说这个。从日常的使用情况来看:这个出现的频率非常高,特别是在框架中,比如Laravel、Slim等都会用到,并且用得非常经典,让人佩服啊。从技术上说:说实话其他的我用的少啊!只是知道简单的用法,对他的理解比较浅显,不敢在这里误导大家,哈哈!今天我要写的内容也不一定都正确,不对之处还请指正。
ArrayAccess
先说 ArrayAccess 吧!ArrayAccess 的作用是使得你的对象可以像数组一样可以被访问。应该说 ArrayAccess 在PHP5中才开始有的,PHP5中加入了很多新的特性,当然也使类的重载也加强了,PHP5 中添加了一系列接口,这些接口和实现的 Class 统称为 SPL。
ArrayAccess 这个接口定义了4个必须要实现的方法:
所以我们要使用ArrayAccess这个接口,就要实现相应的方法,这几个方法不是随便写的,我们可以看一下 ArrayAccess 的原型:
下面我们可以写一个例子,非常简单:
好了,下面我们会结合Slim框架来说在实际中的应用,在Slim中使用非常重要,也非常出色的使用了 container,container继承自Pimple\Container,说到这,就有必要说一下Pimple,pimple是php社区中比较流行的一种ioc容器,pimple中的container类使用了依赖注入的方式来实现实现了程序间的低耦合,可以用composer添加 require "pimple/pimple": "1.*" 添加Pimple到依赖类库,Pimple还是要多看看的,就一个文件,在程序整个生命周期中,各种属性、方法、对象、闭包都可以注册其中,但pimple只是实现了一个容器的概念,还有好多依赖注入、自动创建、关联等功能需要看Laravel才能深刻学到。
在Slim中它使用 container 的类实现了将配置文件依次加载,可以像访问数组一样访问他们,包括displayErrorDetails,renderer, logger,httpVersion,responseChunkSize,outputBuffering,determineRouteBeforeAppMiddleware,displayErrorDetails等等,使他们在框架加载的时候首先被加载。使用的时候直接取就可以了,
下面就是这种加载机制:
其中 defaultSettings 为系统默认配置,userSettings为用户的配置,比如日志,模板等。
下面这段是offsetGet,巧妙使用键值来判断该值是否已经设置过,如果设置过就会直接去取了,没有设置就会转到设置的逻辑。
我们再看看 PimpleContainer,如下图:
我们可以看到其中有个 SplObjectStorage,需要说一下这个,SplObjectStorage是用来存储一组对象,当你需要唯一标识对象的时候。按照官网的说法 PHP SPL SplObjectStorage类实现了Countable, Iterator, Serializable, ArrayAccess四个接口,可实现统计、迭代、序列化、数组式访问等功能。所以SplObjectStorage是一个标准的对象容器。
说到这大家对ArrayAccess应该有所了解了,如果还不清楚,可以多看看Slim的源码,上面写的比较清楚,而且那套源码及其的简练,值得我们学习。
博客会同步更新到我的个人网站,欢迎大家访问!
转载请注明出处,后面会持续更新,谢谢大家!
ArrayAccess
先说 ArrayAccess 吧!ArrayAccess 的作用是使得你的对象可以像数组一样可以被访问。应该说 ArrayAccess 在PHP5中才开始有的,PHP5中加入了很多新的特性,当然也使类的重载也加强了,PHP5 中添加了一系列接口,这些接口和实现的 Class 统称为 SPL。
ArrayAccess 这个接口定义了4个必须要实现的方法:
{ abstract public offsetExists ($offset) //检查偏移位置是否存在 abstract public offsetGet ($offset) //获取一个偏移位置的值 abstract public void offsetSet ($offset ,$value) //设置一个偏移位置的值 abstract public void offsetUnset ($offset) //复位一个偏移位置的值 }
所以我们要使用ArrayAccess这个接口,就要实现相应的方法,这几个方法不是随便写的,我们可以看一下 ArrayAccess 的原型:
/** * Interface to provide accessing objects as arrays. * @link http://php.net/manual/en/class.arrayaccess.php */ interface ArrayAccess { /** * (PHP 5 >= 5.0.0)<br/> * Whether a offset exists * @link http://php.net/manual/en/arrayaccess.offsetexists.php * @param mixed $offset <p> * An offset to check for. * </p> * @return boolean true on success or false on failure. * </p> * <p> * The return value will be casted to boolean if non-boolean was returned. */ public function offsetExists($offset); /** * (PHP 5 >= 5.0.0)<br/> * Offset to retrieve * @link http://php.net/manual/en/arrayaccess.offsetget.php * @param mixed $offset <p> * The offset to retrieve. * </p> * @return mixed Can return all value types. */ public function offsetGet($offset); /** * (PHP 5 >= 5.0.0)<br/> * Offset to set * @link http://php.net/manual/en/arrayaccess.offsetset.php * @param mixed $offset <p> * The offset to assign the value to. * </p> * @param mixed $value <p> * The value to set. * </p> * @return void */ public function offsetSet($offset, $value); /** * (PHP 5 >= 5.0.0)<br/> * Offset to unset * @link http://php.net/manual/en/arrayaccess.offsetunset.php * @param mixed $offset <p> * The offset to unset. * </p> * @return void */ public function offsetUnset($offset); }
下面我们可以写一个例子,非常简单:
<?php class Test implements ArrayAccess { private $testData; public function offsetExists($key) { return isset($this->testData[$key]); } public function offsetSet($key, $value) { $this->testData[$key] = $value; } public function offsetGet($key) { return $this->testData[$key]; } public function offsetUnset($key) { unset($this->testData[$key]); } } $obj = new Test(); //自动调用offsetSet方法 30 $obj['data'] = 'data'; //自动调用offsetExists 33 if(isset($obj['data'])){ echo 'has setting!'; } //自动调用offsetGet var_dump($obj['data']); //自动调用offsetUnset unset($obj['data']); var_dump($test['data']); //输出: //has setting! //data //null
好了,下面我们会结合Slim框架来说在实际中的应用,在Slim中使用非常重要,也非常出色的使用了 container,container继承自Pimple\Container,说到这,就有必要说一下Pimple,pimple是php社区中比较流行的一种ioc容器,pimple中的container类使用了依赖注入的方式来实现实现了程序间的低耦合,可以用composer添加 require "pimple/pimple": "1.*" 添加Pimple到依赖类库,Pimple还是要多看看的,就一个文件,在程序整个生命周期中,各种属性、方法、对象、闭包都可以注册其中,但pimple只是实现了一个容器的概念,还有好多依赖注入、自动创建、关联等功能需要看Laravel才能深刻学到。
在Slim中它使用 container 的类实现了将配置文件依次加载,可以像访问数组一样访问他们,包括displayErrorDetails,renderer, logger,httpVersion,responseChunkSize,outputBuffering,determineRouteBeforeAppMiddleware,displayErrorDetails等等,使他们在框架加载的时候首先被加载。使用的时候直接取就可以了,
下面就是这种加载机制:
<?php namespace Slim; use Interop\Container\ContainerInterface; use Interop\Container\Exception\ContainerException; use Pimple\Container as PimpleContainer; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Slim\Exception\ContainerValueNotFoundException; class Container extends PimpleContainer implements ContainerInterface { /** * Default settings * * @var array */ private $defaultSettings = [ 'httpVersion' => '1.1', 'responseChunkSize' => 4096, 'outputBuffering' => 'append', 'determineRouteBeforeAppMiddleware' => false, 'displayErrorDetails' => false, ]; /** * Create new container * * @param array $values The parameters or objects. */ public function __construct(array $values = []) { //var_dump($values); exit; parent::__construct($values); $userSettings = isset($values['settings']) ? $values['settings'] : []; $this->registerDefaultServices($userSettings); } private function registerDefaultServices($userSettings) { $defaultSettings = $this->defaultSettings; $this['settings'] = function () use ($userSettings, $defaultSettings) { return new Collection(array_merge($defaultSettings, $userSettings)); }; $defaultProvider = new DefaultServicesProvider(); $defaultProvider->register($this); } . . . }
其中 defaultSettings 为系统默认配置,userSettings为用户的配置,比如日志,模板等。
下面这段是offsetGet,巧妙使用键值来判断该值是否已经设置过,如果设置过就会直接去取了,没有设置就会转到设置的逻辑。
public function offsetGet($id) { if (!isset($this->keys[$id])) { throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id)); } if ( isset($this->raw[$id]) || !is_object($this->values[$id]) || isset($this->protected[$this->values[$id]]) || !method_exists($this->values[$id], '__invoke') ) { return $this->values[$id]; } if (isset($this->factories[$this->values[$id]])) { return $this->values[$id]($this); } $raw = $this->values[$id]; $val = $this->values[$id] = $raw($this); $this->raw[$id] = $raw; $this->frozen[$id] = true; return $val; }
我们再看看 PimpleContainer,如下图:
我们可以看到其中有个 SplObjectStorage,需要说一下这个,SplObjectStorage是用来存储一组对象,当你需要唯一标识对象的时候。按照官网的说法 PHP SPL SplObjectStorage类实现了Countable, Iterator, Serializable, ArrayAccess四个接口,可实现统计、迭代、序列化、数组式访问等功能。所以SplObjectStorage是一个标准的对象容器。
说到这大家对ArrayAccess应该有所了解了,如果还不清楚,可以多看看Slim的源码,上面写的比较清楚,而且那套源码及其的简练,值得我们学习。
博客会同步更新到我的个人网站,欢迎大家访问!
转载请注明出处,后面会持续更新,谢谢大家!
相关文章推荐
- 【PHP项目部署一】PHP环境配置
- PHP 删除数组第一个元素和最后一个元素
- vsftpd的配置
- php处理json数据(从服务器获取,post提交)
- php文件上传设置
- OutputDebugString
- php学习的一些见解与观点
- IT footprint
- 如何让没有定义的php变量不报错
- php curl破解图片防盗链
- tftpd32 工具中的 dhcp tftp 使用说明
- laravel5.0 升级到 laravel5.1
- Windows server 08R2 IIS7 创建FTP 包括ftp的账号密码设置
- 修改PHP上传文件大小限制的方法
- PHP设计模式----单例模式(singleton)
- php版DES
- FTP配置说明
- php权限管理的一些细节问题
- PHP 单一入口
- PHP获取POST方式的XML数据