在我们日常使用框架开发的时候经常会看到这样一个现象,主流框架都提供了像访问数组一样访问对象的能力,那么这些框架究竟是怎么实现这样的操作的呢?本文将带你探究这些实现背后的秘密武器--ArrayAccess 接口。
本文是 PHP 内置接口系列文章的第一篇,从这篇文章开始我们探究 PHP 一系列的内置接口的使用。ArrayAccess 是我们日常开发中使用频率比较高的一系列接口之一,他能够给予你像访问数组一样访问对象的能力。
正如上边所介绍的,实现这一访问能力的主要来自于 ArrayAccess 接口,也就是说你只要正确的实现这一接口,在你使用数组式的操作访问你自定义的实现类时,PHP 将会自动调用相关方法实现对应的访问操作。
完整的 ArrayAccess 接口如下:
php
<?php
ArrayAccess {
abstract public boolean offsetExists ( mixed $offset )
abstract public mixed offsetGet ( mixed $offset )
abstract public void offsetSet ( mixed $offset , mixed $value )
abstract public void offsetUnset ( mixed $offset )
}
对应方法的功能如下:
方法 | 功能 |
---|---|
offsetExists | 检查一个偏移位置是否存在,调用 isset()时自动调用 |
offsetGet | 获取一个偏移位置的值,访问具体对象键值时自动调用 |
offsetSet | 设置一个偏移位置的值,给数据赋值时自动调用 |
offsetUnset | 复位一个偏移位置的值 ,销毁对象键值时自动调用 |
php
下面是一个来自于官方手册的实现这里仅作参考:
<?php
/**
* 对象数组访问能力
* 正是如此,你可以像访问数组一样访问一个对象
* @author Yousef Ismaeil <[email protected]>
*/
class ArrayAndObjectAccess implements ArrayAccess {
private $data = [];
/**
* 通过键值来访问数组对象值
* @param 访问数据的键值
* @access public
*/
public function &__get ($key) {
return $this->data[$key];
}
/**
* 向数组(对象)设置一个值
* @param 需要设置数据的键(数据的key,对象的属性)
* @param mixed 对应键的值
* @access public
*/
public function __set($key,$value) {
$this->data[$key] = $value;
}
/**
* 检测数组(对象)中是否存在一个值
* @param string 需要被检测的数据的键
* @access public
* @return boolean
* @abstracting ArrayAccess
*/
public function __isset ($key) {
return isset($this->data[$key]);
}
/**
* 通过键来销毁一个数组、对象
* @param string 需要被销毁对象的键
* @access public
*/
public function __unset($key) {
unset($this->data[$key]);
}
/**
* 给对应的数组,对象属性赋值
* @param string 需要被设置的数组的键,对象的属性名称
* @param mixed 需要被设置数组的值对象属性对应的值
* @access public
* @abstracting ArrayAccess
*/
public function offsetSet($offset,$value) {
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}
/**
* 检测数组偏移,对象属性值是否存在
* @param string 被检测的键
* @access public
* @return boolean
* @abstracting ArrayAccess
*/
public function offsetExists($offset) {
return isset($this->data[$offset]);
}
/**
* 销毁对应的数组偏移数据,对象对应的数据
* @param 需要被销毁的键
* @access public
* @abstracting ArrayAccess
*/
public function offsetUnset($offset) {
if ($this->offsetExists($offset)) {
unset($this->data[$offset]);
}
}
/**
* 返回对应的数组偏移数据,对象对应的数据
* @param string 需要被返回的数组的键,对象的属性
* @access public
* @return mixed
* @abstracting ArrayAccess
*/
public function offsetGet($offset) {
return $this->offsetExists($offset) ? $this->data[$offset] : null;
}
}
需要指出的是这一接口紧实现了,数组式的对象访问能力,诸如数组的迭代,count 等操作,如果需要相关的功能你还需要同时实现 Iterator 接口和 Countable 接口。