PHP的$this变量

手册上的一个有意思的小示例。

http://www.php.net/manual/zh/language.variables.basics.php

	$this = 'text'; // error
	$name = 'this';
	$$name = 'text'; // sets $this to 'text'
	echo $$name;

在PHP的词法分析时,$this变量是符合其规则的,在语法解析生成中间代码时,PHP内核会根据变量类型在生成赋值的中间代码时判断是否为$this变量,如果是则报错。这里为什么要报错呢?因为this作为一个特殊的变量,在对象的成员方法等调用初始化时会将this变量添加到活动符号表。

在类的成员方法里面,可以用 ->(对象运算符):$this->property(其中 property 是该属性名)这种方式来访问非静态属性。

当一个方法在类定义内部被调用时,有一个可用的伪变量 $this。$this 是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象静态调用时也可能是另一个对象)。

在词法分析、语法分析并生成中间代码时,$this作为一个特殊的变量存在,特别是在生成中间代码时,代码中充斥着对于this的特殊处理。这些都是为后面的运行做准备,如识别标记出某处使用this变量,在存储opcode的zend_op_array结构体中专门有一个变量this_var标识是否有this变量。一个函数或一个类方法都会生成一个新的zend_op_array,在生成中间代码时,判断当前变量是否为this变量。

this变量在执行过程中会有两种存在状态,一种是全局传递的状态,存储在EG(This),一种是当前作用域状态,以this变量存储在EG(active_symbol_table)(当前执行环境的活动符号表)。
在我们执行一个 op_array 时,比如一个对象的方法,PHP内核会给这个 op_array 生成一个 zendexecutedata ,在生成初始化时,EG(This) 会添加到EG(active_symbol_table) 。
在方法调用过程中,如果有用到this变量,则会直接取EG(active_symbol_table)的值。

那么一个对象中的EG(This)在哪里初始化呢?
就EG(This)变量本身来说,在我们初始化PHP的执行环境时,它和其它全局变量(如EG(scope)等)一样都会被初始化为NULL。
对于一个对象来说,当我们创建了一个对象,调用时,PHP内核会将当前获得的对象直接赋值给EG(This),而这个当前获得的对象是在通过new操作生成对象时创建的对象本身。

如下这个简单示例:

	class Foo {
	     public $var = 10;
 
	     function t() {
	          echo $this->var;     
	     }
 
	     function t2() {
	     	echo 33;
		}
	}
 
	$foo = new Foo();
	$foo->t();

其主程序流程生成的中间代码如下:

        function name:  (null)
	number of ops:  8
	compiled vars:  !0 = $foo
	line     # *  op                           fetch          ext  return  operands
	---------------------------------------------------------------------------------
	   2     0  >   NOP                                                      
	  15     1      ZEND_FETCH_CLASS                              4  :1      'Foo'
	         2      NEW                                              $2      :1
	         3      DO_FCALL_BY_NAME                              0          
	         4      ASSIGN                                                   !0, $2
	  16     5      ZEND_INIT_METHOD_CALL                                    !0, 't'
	         6      DO_FCALL_BY_NAME                              0          
	         7    > RETURN                                                   1

this变量原始的对象值出生在 opcode NEW,经过了赋值(ASSIGN)后,在方法初始化时,将变量本身传递给执行环境的调用者,调用者又在执行调用(DO_FCALL_BY_NAME)时将变量传递给EG(This),当执行这个方法的op_array时,初始化当前作用域的环境(zend_execute_data)时,会将EG(This)作为$this变量添加到活动符号表,后续方法中的$this变量的使用就会直接取符号表的变量。

PHP的$this变量》上有1条评论

  1. 刘金虎

    你好,我是一位自学者,看到你的博客,你应该是一位资深的程序员,想请教你一个学习方法,现在我自学完所有基础,简单接触一些框架,想自动手写一些简单的网站来巩固基础和提升自己,适合模访一些什么网站,最好是从简单到复杂进阶。还有一些好的学习方法和学习步骤,希望得到你的回复,感谢!

    回复

刘金虎进行回复 取消回复

电子邮件地址不会被公开。 必填项已用*标注


*

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>