【PHP】ArrayAccess、Countable与IteratorAggregate

ArrayAccessCountableIteratorAggregate 是编写PHP框架中常用的几个接口。

它们能让我们像使用数组一样去操作、遍历与计算对象的成员数量。

以下简述这三个接口的基本使用。

ArrayAccess

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
|--------------------------------------------------------------------------
| ArrayAccess (数组式访问) 接口
|--------------------------------------------------------------------------
|
| 提供像访问数组一样访问对象的能力的接口.
|
|
*/
class Obj implements ArrayAccess
{
private $container = [];
public function __construct()
{
$this->container = [
"one" => 1,
"two" => 2,
"three" => 3
];
}
// 设置一个偏移位置的值
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
// 获取一个偏移位置的值
public function offsetGet($offset)
{
return isset($this->container[$offset]) ? $this->container[$offset] : 'hi,它并不存在~';
}
// 复位一个偏移位置的值
public function offsetUnset($offset)
{
unset($this->container[$offset]);
}
// 检查一个偏移位置的值是否存在
public function offsetExists($offset)
{
return isset($this->container[$offset]);
}
}
$obj = new Obj();
if (isset($obj['one'])) { // 自动调用 `offsetExists`
// 自动调用 `offsetGet`
echo $obj['one']; // 1
// 自动调用 `offsetSet`
$obj['one'] = 'one';
echo $obj['one']; // one
var_dump($obj['one']); // string(3) "one"
// 自动调用 `offsetUnset`
unset($obj['one']);
var_dump($obj['one']); // string(19) "hi,它并不存在~"
}

Countable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
|--------------------------------------------------------------------------
| Countable 接口
|--------------------------------------------------------------------------
|
| 类实现 `Countable` 可被用于 `count()` 函数.
|
|
*/
class Dragonfly implements Countable
{
public $likes = ['coding', 'music', 'anime'];
public function count()
{
return count($this->likes);
}
}
$df = new Dragonfly();
/**
* 若没有实现 `Countable` 接口,结果只会出现 `int(1)`
* 实现该接口后,使用 `count` 函数时,会自动调用类中 `count()`
*/
var_dump(count($df)); // int(3)

IteratorAggregate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
|--------------------------------------------------------------------------
| IteratorAggregate (聚合式迭代器) 接口
|--------------------------------------------------------------------------
|
| 创建外部迭代器的接口
|
|
*/
class Hobby implements IteratorAggregate
{
public $coding = 'PHP、Javascript、Golang、Python';
public $music = 'Kardusen、Silent Roar、Anemo';
public $anime = 'another、尸鬼';
/*
|--------------------------------------------------------------------------
| ArrayIterator
|--------------------------------------------------------------------------
|
| 这个迭代器允许在遍历数组和对象时删除和更新值与键
| 注意,它只迭代访问修饰符为 `public` 的成员变量。
|
*/
public function getIterator()
{
return new ArrayIterator($this);
}
}
$hobby = new Hobby();
/*
* key: coding, value: PHP、Javascript、Golang、Python
* key: music, value: Kardusen、Silent Roar、Anemo
* key: anime, value: another、尸鬼
*
*/
foreach ($hobby as $k => $v) {
echo "key: $k" . ", value: $v<br />";
}
/**
* 若将类中的成员变量作如下改变:
* public $coding = 'PHP、Javascript、Golang、Python';
* protected $music = 'Kardusen、Silent Roar、Anemo';
* private $anime = 'another、尸鬼';
*
* 结果会有所改变,因为该迭代器只遍历访问修饰符为 `public` 的成员变量。
* key: coding, value: PHP、Javascript、Golang、Python
*/