ArrayAccess如何工作?

时间:2011-01-01 16:31:43

标签: php php-extension spl

我一直在阅读SPL中常用的PHP接口,例如IteratorCountableArrayAccess。但是,我不明白它们是如何工作的。

他们的实现是否会修改PHP的核心功能,例如重载[]数组运算符?

我还读过有关Operator扩展的内容,它提供了以与低级语言相同的方式重载其他运算符的能力。由于Operator扩展明确地修改了PHP核心,我想知道ArrayAccess在幕后是否以相同的方式起作用?

我是一个修补匠,因此我发现很难在不知道引擎盖的情况下使用它。

1 个答案:

答案 0 :(得分:11)

PHP和PHP扩展构建在Zend引擎之上。他们将Zend Engine功能暴露给用户自定义(PHP脚本)并添加他们自己的功能,这些功能要么暴露给用户区域,要么暴露给其他PHP扩展。

Zend Engine为对象模型提供了一种访问对象维度的方法(ArrayAccess公开的功能)和用于迭代对象的一般迭代机制(Iterator的同义词)。该对象模型由许多处理程序组成,PHP和任何扩展可以替换一种对象(zend object handlers)。在它的对象模型中,Zend引擎实现了一种标准类型的对象(“zend对象”);每个对象都遵循zend_object数据结构,每个类 - 这是一个低级对象接口不知道的概念,除了提供检索它的方法 - 由zend_class_entry结构)。

ArrayAccess实际上不是SPL接口;它在Zend Engine本身中定义。 zend对象的read_dimension / write_dimension / has_dimension低级处理程序以这样的方式实现:它们检查对象是否实现了这样的接口,如果是这种情况则调用相应的方法(见here)。

Iterator也不是SPL界面;它也在Zend引擎中定义。在这种情况下,对此接口的支持是在稍高的级别完成的。低级对象处理程序对对象迭代一无所知;这是Zend Objects的一个属性。 zend_class_entry结构在此处有两个相关成员:iterator_funcs字段和get_iterator字段。这些定义了迭代器操作和状态以及如何创建新的迭代器。特别是对于Iterator,当一个类在运行时注册时,会检查它是否实现了该接口,如果是,则将该类的zend_class_entry变量中的相关字段设置为本机方法将本机迭代接口桥接到PHP方法。如果编写一个PHP扩展,可以选择编写本机迭代器(本机实现迭代方法),或者像在用户区中一样,实现Iterator并编写PHP方法(在本例中为本机) PHP方法)用于几个操作,如界面描述。

Countable接口是唯一一个实际上是SPL接口的接口; Zend Engine对此一无所知。它的功能源自count function的实现检查其存在的事实,并且如果接口存在则调用count方法。

操作员扩展程序以更低级别的设置运行。在运行时,直接写入Zend Engine的内存并替换PHP代码编译的操作码的处理程序(现在,例如ZEND_ASSIGN_ADD有一个新的本机实现,这遵循一些PHP函数/方法用户可以选择)。