Press "Enter" to skip to content

深入理解PHP原理之变量作用域(Scope in PHP)

我前面的文章(深入理解PHP原理之变量(Variables inside PHP))介绍了PHP变量的内部表示,但是,问题是,这些内部表示是如何和用户脚本中的变量联系起来的呢?也就是说,如果我在脚本中写下:

<?php
  $var = "laruence";
  echo $var;
?>

ZE是如何把我的变量var和内部结构zval联系起来的呢?
深入理解PHP原理之变量中讲过,PHP内部都是使用zval来表示变量的,但是对于上面的脚本,我们的变量是有名字的, var。而zval中并没有相应的字段来体现变量名。
如果你想到了PHP内部一定有一个机制,来实现变量名到zval的映射。那么你真的是很聪明,;)
在PHP中,所有的变量都会存储在一个数组中(确切的说是hash table), 并且,PHP也是通过不同的数组来实现变量的作用域的。
当你创建一个变量的时候,PHP会为这个变量分配一个zval,填入相应的变量值,然后将这个变量的名字,和指向这个zval的指针填入一个数组中。然后,当你获取这个变量的时候,PHP会通过查找这个数组,获得对应的zval。
查看_zend_executor_globals结构(这个结构在PHP的执行器保存一些执行相关的上下文信息)

struct _zend_executor_globals {
	....
    HashTable *active_symbol_table;/*活动符号表*/
    HashTable symbol_table;     /*全局符号表*/
    HashTable included_files;
    jmp_buf *bailout;
    int error_reporting;
	.....
}
 

其中,全局符号表,保存了在顶层作用域(就是不在任何函数,对象内)的变量。每当调用一个函数(对象的方法)的时候,就会为这个函数创建一个活动符号表,所有在这个函数内定义的变量,都会保存在这个活动符号表中。
对,这就是PHP的变量作用域的实现方式! 举个列子:

  <?php
	$var = "I am in the global symbol table";
    function sample($para){
        $var = "I am in the active symbol table";
		echo $var;
 	}
    sample($var);
    echo $var;
  ?>

在函数sample外面的变量$var,它会被填入全局符号表中,与他对应的有一个zval指针,这个zval保存了一个字符串"I am in the global symbol table".
函数内的$var, 它会被填入属于函数sample的活动符号表中,一样的,与他对应的zval中,保存着字符串"I am in the active symbol table
".
比较特殊的,就是函数sample的参数$para了,这个$para是保存在sample的活动符号表的,但是与他对应的zval指针,会指向一个保存一份全局变量$var的copy的zval(严格来讲不是copy,是引用,这个涉及到变量的copy on write机制,我会在以后介绍)。
我们都知道PHP对于简单变量是传值调用的,但是,我要告诉你的是,PHP并不是简单的通过复制一个zval来实现传值的,呵呵,留个悬念,等我下回分解.

19 Comments

  1. Case Soltuion
    Case Soltuion August 4, 2018

    I Must Say We Should Have An Online Discussion On This.

  2. […] 在这个过程中, 会涉及到对PHP的函数调用, PHP的传参, PHP的一些全局变量的知识, 这些知识在我之前的文章中都有过涉及, 大家可以翻阅: 深入理解PHP原理之函数 深入理解PHP原理之变量作用域等等. […]

  3. JosephBah
    JosephBah May 16, 2017

    Поздравляю, отличное сообщение
    cpadollar.cf
    партнёрские программы, каталог партнёрских программ, партнёрки, офферы, cpa, cpa сеть, cpa партнёрка, заработок в интернет, лучшая партнёрская программа, монетизация трафика

  4. […] 在前面的文章中我已经介绍了PHP的变量的内部表示(深入理解PHP原理之变量(Variables inside PHP)),以及PHP中作用域的实现机制(深入理解PHP原理之变量作用域(Scope inside PHP))。这节我们就接着前面的文章,继续介绍PHP中变量分离和引用的概念: […]

  5. 刘宝成
    刘宝成 April 5, 2013

    先顶一个,本人初学php,始终搞不定变量名与栈中的变量值的对应关系,对于这个知识点查了好几天了,似乎大家的认识也都比较模糊,我认为正因为php是动态类型的语言,所以我们才要把它的基本原理搞清楚,知道它是怎么给我们转型的,不然
    模模糊糊的以后肯定要栽跟头的。非常感谢楼主这样的php高手给我们这些初学者进行深入浅出的讲解!

  6. selfimpr
    selfimpr September 19, 2011

    我们都知道PHP对于简单变量是传值调用的,但是,我要告诉你的是,PHP并不是简单的通过复制一个zval来实现传值的,呵呵,留个悬念,等我下回分解.
    请问, 这个指的是”copy-on-write”还是有其他的知识??

  7. […] 在这个过程中, 会涉及到对PHP的函数调用, PHP的传参, PHP的一些全局变量的知识, 这些知识在我之前的文章中都有过涉及, 大家可以翻阅: 深入理解PHP原理之函数 深入理解PHP原理之变量作用域等等. […]

  8. sky
    sky February 9, 2009

    既然symbol_table和*active_symbol_table都是HashTable结构,那变量名是放在哪呢,好像不知道symbol_table结构中哪个元素作为存放变量名和值用,即key/value

  9. 雪候鸟
    雪候鸟 September 11, 2008

    恩, 是应该介绍这方面的东西了

  10. xiaoj
    xiaoj September 11, 2008

    楼主后面是不是准备讲refererce,copy on write,change on write了

  11. 雪候鸟
    雪候鸟 August 31, 2008

    呵呵,不好意思啊,最近项目很紧,等忙过这阵,我一次多写点。

  12. 爱上
    爱上 August 30, 2008

    咋不分解了啦

Comments are closed.