Chinaunix

标题: PHP中的Trait语法深度解析 [打印本页]

作者: 傲笛飞血    时间: 2011-08-28 07:20
标题: PHP中的Trait语法深度解析
Trait是PHP5.4中新加入的一种的语法结构,用来方便我们实现对象的扩展,是除extend、implements外的另外一种扩展对象的方式。
我将在接下来的内容中介绍以下内容:


一、对象结构的修改

为了实现Trait语法,PHP内核中对实现对象的结构体做了修改:
  1. struct _zend_class_entry
  2. {
  3.         ... ...
  4.         zend_class_entry **traits;
  5.         zend_uint num_traits;
  6.         zend_trait_alias **trait_aliases;
  7.         zend_trait_precedence **trait_precedences;
  8.         ... ...
  9. }
复制代码
[p]其中增加了4个属性,其中比较关键的为两个:
@zend_class_entry **traits;
这个存放着这个类实现的各个trait,可以看出,每一个trait在内核中和对象一样,也是通过zend_class_entry结构实现的。
[p]@num_traits
这个对象实现的trait个数。

二、语法解析及功能实现

理解了上面两个属性的含义后,这是我们便可以开始看PHP是如何来解析trait语法结构的。
  1. <?php
  2. class a
  3. {
  4.         use b;
  5. }
复制代码

这样我们的对象a便使用b这个trait。”use b;”对应的token为(去除了最后的分号token):
  1. T_USE :use
  2. T_WHITESPACE :
  3. T_STRING :t_a
复制代码


我们顺着T_USE在zend_language_parser.y中寻找,其实use有两个用途,一个与trait有关,一个与namespace有关,所以在这个文件中也能相应的找个两个地方,但我们这一次只关心它与trait配对的那个。在582行左右,我们找到了相应的几条与trait有关的解析规则,它们都集中在 582行左右,这里只举例:

  1. trait_use_statement:
  2.     T_USE trait_list trait_adaptations;
  3. trait_list:
  4.     fully_qualified_class_name { zend_do_implements_trait(&$1 TSRMLS_CC); }
  5.     | trait_list ',' fully_qualified_class_name { zend_do_implements_trait(&$3 TSRMLS_CC); };
复制代码


use b;对应的是zend_do_implements_trait函数,我们检查这个函数发现,它增加了一条ZEND_ADD_TRAIT指令,对应的是zend_do_implement_trait函数(注意:和前面的相比少了一个s),意思便是向当前正在定义的对象中的(zend_class_entry **traits;)属性里添加一个新的trait,并更新(zend_uint num_traits)等。

在我们对象定义结束后,会调用zend_do_end_class_declaration()函数,而这个函数在PHP5.4版本中做了修改,如果它检测到当前定义的对象使用了trait,则会增加一条ZEND_BIND_TRAITS指令,ZEND虚拟机在执行这条指令的时候便调用zend_do_bind_traits函数来将trait中定义的属性、方法copy给对象,是的,就是完完全全的Copy!
现在一切水落石出,我们已经找到了最关键的zend_do_bind_traits函数,请点击图片看注释:


首先,将trait中定义的函数copy给对象ce,使用的zend_do_traits_method_binding函数,请点击图片看注释:





然后再把trait中定义的属性copy给对象ce,使用的是zend_do_traits_property_binding函数,请点击图片看注释:


好了,先写这么多,大体的流程我们已经分析完了,现在我们便可以总结出几点东西来了:


昨天在wordpress上写的时候,对贴大篇幅代码这块一直很头疼,要么超长折行、要么不支持源码与非源码自由切,一切换>就成>了。到最后索性使用了图片,哪位兄台可以给推荐个好用的解决方案。
作者: renxiao2003    时间: 2011-08-28 10:04
PHP出5.4了吗?
作者: renxiao2003    时间: 2011-08-28 10:08
看到出5.4 alpha3了。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2