所有前面示例中的代码, 都是你曾经在php用户空间编写过代码的C语言的独立版本. 如果你做的项目需要和php扩展进行粘合, 那么你就至少需要链接一个外部库.
过滤器和上下文可以让普通的流类型行为被修改, 或通过INI设置影响整个请求, 而不需要直接的代码修改. 使用本章设计的计数, 你可以使你自己的包装器实现更加强大, 并且可以对其他包装器产生的数据进行改变.接下来, 我们将离开PHPAPI背后的工作, 回到php构建系统的机制, 产生更加复杂的扩展链接到其他应用, 找到更加容易的方法, 使用工具集处理重复的工作.
过滤器作为读写操作的流内容传输过程中的附加阶段. 要注意的是直到php 4.3中才加入了流过滤器, 在php 5.0对流过滤器的API设计做过较大的调整. 本章的内容遵循的是php 5的流过滤器规范.
每个流的上下文包含两种内部消息类型. 首先最常用的是上下文选项. 这些值被安排在上下文中一个二维数组中, 通常用于改变流包装器的初始化行为. 还有一种则是上下文参数, 它对于包装器是未知的, 当前提供了一种方式用于在流包装层内部的事件通知.php_stream_context *php_stream_context_alloc(void);
php常被提起的一个特性是流上下文. 这个可选的参数甚至在用户空间大多数流创建相关的函数中都可用, 它作为一个泛化的框架用于向给定包装器或流实现传入/传出额外的信息.
无论是暴露远程网络I/O还是本地数据源的流资源, 都允许你的扩展在核心数据上挂在操纵函数的钩子, 避免重新实现单调的描述符管理和I/O缓冲区工作. 这使得它在用户空间环境中更加有用, 更加强大.下一章将通过对过滤器和上下文的学习结束流包装层的学习, 过滤器和上下文可以用于选择默认的流行为, 甚至过程中修改数据.
并不是所有的流操作都涉及到资源的操纵. 有时候也需要查看活动的流在某个时刻的状态, 或检查潜在可打开的资源的状态.这一节流和包装器的ops函数都是在相同的数据结构php_stream_statbuf上工作的, 它只有一个元素: posix标准的struct statbuf. 当本节的某个函数被调用时, 将尝试填充尽可能多的statbuf元素的成员.
5个静态包装器操作中的4个用来处理不是基于I/O的流资源操作. 你已经看到过它们并了解它们的原型;
为了演示包装器和流操作的内部工作原理, 我们需要重新实现php手册的stream_wrapper_register()一页示例中的var://包装器.此刻, 首先从下面功能完整的变量流包装实现开始. 构建他, 并开始检查每一块的工作原理.译注: 为了方便大家阅读, 对代码的注释进行了适量补充调整, 此外, 由于phpapi的调整, 原著中的代码不能直接在译者使用的php-5.4.10中运行, 进行了适当的修改.
除了url_stat()函数, 包装器操作中在const char *label元素之前的每个操作都可以用于激活的流实例上. 每个函数的意义如下:stream_opener() 实例化一个流实例. 当某个用户空间的fopen()函数被调用时, 这个函数将被调用. 这个函数返回的php_stream实例是fopen()函数返回的文件资源句柄的内部表示.
对于给定的流实例, 比如文件流和网络流, 它们的不同在于上⼀一章你使用的流创建函数返回的php_stream结构体中的ops成员.typedef struct _php_stream { ... php_stream_ops *ops; ...} php_stream;php_stream_ops结构体定义的是一个函数指针集合以及一个描述标记.
php的流最强力的特性之一是它可以访问众多数据源: 普通文件, 压缩文件, 网络透明 通道, 加密网络, 命名管道以及域套接字, 它们对于用户空间以及内部都是统⼀的API.
本章中你接触了一些基于流的I/O的内部表象. 下一章将演示做呢样实现自己的协议包装, 甚至是定义自己的流类型.
一个基于流的原子操作并不需要实际的实例. 下面这些API仅仅使用URL执行这样的操作:int php_stream_stat_path(char *path, php_stream_statbuf *ssb);和前面的php_stream_stat()类似, 这个函数提供了一个对POSIX的stat()函数协议依赖的包装. 要注意, 并不是所有的协议都支持URL记法, 并且即便支持也可能不能报告出statbuf结构体中的所有成员值.
通常, 直接的文件描述符相比调用流包装层消耗更少的CPU和内存; 然而, 这样会将实现某个特定协议的所有工作都堆积到作为扩展开发者的你身上. 通过挂钩到流包装层, 你的扩展代码可以透明的使用各种内建的流包装, 比如HTTP, FTP, 以及它们对应的SSL版本, 另外还有gzip和bzip2压缩包装.
PHP用户空间中所有的文件I/O处理都是通过php 4.3引入的php流包装层处理的。在内部,扩展代码可以选择使用stdio或posix文件处理和本地文件系统或伯克利域套接字进行通信,或者也可以调用和用户空间流I/O相同的API。
在这章,你探索了PHP中最古老的特性,也可以说是PHP健壮可移植性的最大的问题所在。对于每个有用的INI设置,它对编程的障碍就是随时都会出现它,这让编程越来越复杂。INI设置是一把双刃剑,所以在使用之前一定要深思熟虑,不然造成的后果将是长久的;胡乱使用将使你的系统出现很多不可预测的问题。
INI条目被定义在一个完整的独立的的块,位于上文中所说的MINIT方法的同一个源文件,并且用下面的一对宏来定义,并在这对宏之间放入一个或者多个条目PHP_INI_BEGIN()和PHP_INI_END()这些宏方法和上一章所提到的ZEND_BEGIN_MODULE_GLOBALS()和ZEND_END_MODULE_GLOBALS()有着相同的用法。
在前面的一章,我们已经学会了MINIT、MSHUTDOWN函数,以及RINIT和RSHUTDOWN等函数的使用,这里我们将介绍并学习ini设置的使用。
通过本章的课程,我们深入了解了PHP的生命周期,常量、全局变量和超级全局变量的定义和使用。在下一章中,你会学会如何声明和使用的php.ini值。
关注时代Java