首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > PHP >

[通译][php扩展和嵌入式]第11章-php5对象

2013-04-09 
[翻译][php扩展和嵌入式]第11章-php5对象全部翻译内容pdf文档下载地址: http://download.csdn.net/detail/

[翻译][php扩展和嵌入式]第11章-php5对象

全部翻译内容pdf文档下载地址: http://download.csdn.net/detail/lgg201/5107012

本书目前在github上由laruence(http://www.laruence.com)和walu(http://www.walu.cc)两位大牛组织翻译. 该翻译项目地址为: https://github.com/walu/phpbook

本书在github上的地址: https://github.com/goosman-lei/php-eae

未来本书将可能部分合并到phpbook项目中, 同时保留一份独立版本.


原书名: <Extending and Embedding PHP>

原作者: Sara Golemon

译者: goosman.lei(雷果国)

译者Email: lgg860911@yahoo.com.cn

译者Blog: http://blog.csdn.net/lgg201

php5对象

将php5的对象和它的先辈php4对象进行比较实在有些不公平, 不过php5对象使用的API函数还是遵循php4的API构建的. 如果你已经阅读了第10章"php4对象", 你将会对本章内容多少有些熟悉. 在开始本章之前, 可以像第10章开始时一样, 重命名扩展为sample3并清理多余的代码, 只保留扩展的骨架代码.

进化史

在php5对象变量中有两个关键的组件. 第一个是一个数值的标识, 它和第9章"资源数据类型"中介绍的数值资源ID非常相似, 扮演了一个用来在对应表中查找对象实例的key的角色. 在这个实例表中的元素包含了到zend_class_entry的引用以及内部的属性表.

第二个元素是对象变量的句柄表, 使用它可以自定义Zend引擎对实例的处理方式. 在本章后面你将看到这个句柄表.

zend_class_entry

类条目是你在用户空间定义的类的内部表示. 正如你在前一章所见, 这个结构通过调用INIT_CLASS_ENTRY()初始化, 参数为类名和它的函数表. 接着在MINIT阶段使用zend_register_internal_class()注册.

类型标记

含义

ZEND_ACC_STATIC

方法可以静态调用.实际上,这就表示,方法如果通过实例调用, $this或者更确切的说this_ptr,并不会被设置到实例作用域中

ZEND_ACC_ABSTRACT

方法并不是真正的实现.当前方法应该在被直接调用之前被子类覆写.

ZEND_ACC_FINAL

方法不能被子类覆写



可见性标记

含义

ZEND_ACC_PUBLIC

可以在对象外任何作用域调用.这和php4方法的可见性是一样的

ZEND_ACC_PROTECTED

只能在类中或者它的子类中调用

ZEND_ACC_PRIVATE

只能在类中调用


比如, 由于你前面定义的Sample3_SecondClass::helloWorld()方法不需要对象实例, 你就可以将它的定义从简单的ZEND_ACC_PUBLIC修改为ZEND_ACC_PUBLIC | ZEND_ACC_STATIC, 这样引擎知道了就不会去提供(实例)了.

魔术方法

除了ZE1的魔术方法外, ZE2新增了很多魔术方法, 如下表(或者可以在http://www.php.net/language.oop5.magic中找到)


方法

用法

__construct(...)

可选的自动调用的对象构造器(之前定义的是和类名一致的方法).如果__construct()和classname()两种实现都存在,在实例化的过程中,将优先调用__construct()

__destruct()

当实例离开作用域,或者请求整个终止,都将导致隐式的调用实例的__destruct()方法去处理一些清理工作,比如关闭文件或网络句柄.

__clone()

默认情况下,所有的实例都是真正的引用传值.在php5中,要想真正的拷贝一个对象实例,就要使用clone关键字.当在一个对象实例上调用clone关键字时, __clone()方法就会隐含的被执行,它允许对象去复制一些需要的内部资源数据.

__toString()

在用文本表示一个对象时,比如当直接在对象上使用echo或print语句时, __toString()方法将自动的被引擎调用.类如果实现这个魔术方法,应该返回一个包含描述对象的当前状态的字符串.

__get($var)

如果脚本中请求一个对象不可见的属性(不存在或者由于访问控制导致不可见)时, __get()魔术方法将被调用,唯一的参数是所请求的属性名.实现可以使用它自己的内部逻辑去确定最合理的返回值返回.

__set($var, $value)

和__get()很像, __set()提供了与之相反的能力,它用来处理赋值给对象的不可见属性时的逻辑.__set()的实现可以选择隐式的在标准属性表中创建这些变量,以其他存储机制设置值,或者直接抛出错误并丢弃值.

__call($fname, $args)

调用对象的未定义方法时可以通过使用__call()魔术方法实现漂亮的处理.这个方法接受两个参数:被调用的方法名,包含调用时传递的所有实参的数值索引的数组.

__isset($varname)

php5.1.0之后, isset($obj->prop)的调用不仅是检查$obj中是否有prop这个属性,它还会调用$obj中定义的__isset()方法,动态的评估尝试使用动态的__get()和__set()方法是否能成功读写属性

__unset($varname)

类似于__isset(), php 5.1.0为unset()函数引入了一个简单的OOP接口,它可以用于对象属性,虽然这个属性可能在对象的标准属性表中并不存在,但它可能对于__get()和__set()的动态属性空间是有意义的,因此引入__unset()来解决这个问题.


还有其他的魔术方法功能, 它们可以通过某些接口来使用, 比如ArrayAccess接口以及一些SPL接口.

在一个内部对象的实现中, 每个这样的"魔术方法"都可以和其他方法一样实现, 只要在对象的方法列表中正确的定义PHP_ME()以及PUBLIC访问修饰符即可.对于 __get(), __set(), __call(), __isset()以及__unset(), 它们要求传递参数, 你必须定义恰当的arg_info结构来指出方法需要一个或两个参数. 下面的代码片段展示了这些木梳函数的arg_info和它们对应的PHP_ME()条目:

INIT_CLASS_ENTRY(ce, PHP_SAMPLE3_SC_NAME,                        php_sample3_sc_functions);php_sample3_sc_entry =            zend_register_internal_class(&ce TSRMLS_CC);php_sample3_sc_entry->create_object= php_sample3_sc_create;php_sample3_register_constants(php_sample3_sc_entry);zend_class_implements(php_sample3_sc_entry TSRMLS_CC,            1, php_sample3_iface_entry);

这两种方法唯一可预见的不同是它们发生的时机不同. 引擎在碰到new Sample3_SecondClass后会在处理构造器及它的参数之前调用create_object. 通常, 你计划覆盖的各个点使用的方法(create_object Vs. __construct)应该一致.

译注: php-5.4.9中, xxx_property/xxx_dimension这一组句柄的原型是不一致的, 因此, 按照原著中的示例, 直接将xxx_property/xxx_dimension进行映射已经不能工作, 要完成上面的功能, 需要对4个句柄均包装一个函数去映射. 由于译者没有详细跟踪具体在哪一个版本发生了这些改变, 因此这里不给出译者测试的示例(没有做兼容性处理检查), 如果读者碰到这个问题, 请检查自己所使用php版本中两组句柄原型的差异并进行相应修正.

小结

毋庸置疑, php5/ZE2的对象模型比它的前辈php4/ZE1中的对象模型更加复杂. 在看完本章中介绍的所有特性和实现细节后, 你可能已经被它的所包含的信息量搞得手足无措. 幸运的是, php中在OOP之上有一层可以让你选择你的任务所需的部分而不关心其他部分. 找到复杂性之上一个舒适的层级开始工作, 剩下的都会顺起来的.

现在已经看完了所有的php内部数据类型, 是时候回到之前的主题了: 请求生命周期. 接下来的两章, 将在你的扩展中使用线程安全全局变量增加内部状态, 定义自定义的ini设置, 定义常量, 以及向使用你扩展的用户空间脚本提供超级全局变量.



目录上一章: php4对象下一章: 启动,终止,以及其中的一些点

热点排行