php - ArrayAccess 如何工作?

标签 php php-extension spl

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

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

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

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

最佳答案

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

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

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

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

Countable 接口(interface)是唯一一个实际上是 SPL 接口(interface)的接口(interface); Zend 引擎对此一无所知。它的功能源自以下事实:count function 的实现。检查它是否存在,如果接口(interface)存在则调用 count 方法。

运算符(operator)扩展在更底层的设置下运行。在运行时,直接写入 Zend 引擎的内存并替换 PHP 代码编译成的操作码处理程序(因此现在例如 ZEND_ASSIGN_ADD 有一个新的 native 实现,它遵循一些 PHP 函数/用户可以选择的方法)。

关于php - ArrayAccess 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4574703/

相关文章:

php - 在本地主机上使用 crontab 的 cronjob 没有结果

php - 在 Mac 上的 XAMPP 上安装 PHP 7.0 国际化扩展 (Intl)

php - 检测服务器上是否安装了 FreeType PHP 扩展

php - array_map vs 循环和操作

php - 使用 SplObjectStorage 作为数据映射,是否可以使用可变数组作为数据?

php - 反向SPL对象存储

javascript - 使用ajax将php数组传递给javascript

php - session 过期后用帖子重定向

php - 从不同的电脑连接到 wamp 服务器

php - 如何将 zval* 转换为对象?