msgbartop
PHP语言, PHP扩展, Zend引擎相关的研究,技术,新闻分享 – 左手代码 右手诗
msgbarbottom

08 Dec 10 如何获取一个变量的名字

比如, 我提供一个查询服务, 用户可以提交一个人的名字和年龄做为查询条件.

假设我要查询一个名字叫做”laruence”, 年龄是27的人, 我认为这个人的定义的查询token可以写做:

   laruence=27

不幸的是, 当这样的一个token做为query string提交给服务器的处理脚本的时候, 你就会发现, 诶,,我不知道用户名是什么,,,

好吧, 于是, 你就只好这么写:

username=laruence&age=27

那么, 能否获取到一个变量的名字呢?

首先, 从可能性上分析,

我们知道, 在C语言中, 所有的符号在编译器都被”替换”掉了.

而在PHP中, 所有的变量都存储在称为”符号表”的HastTable结构中. 在解析执行的过程中, 依旧保留着着”符号”信息, 所以, 肯定是可以获取到的.

而在PHP中, 符号的作用域是和活动符号表相关联的. 同一时间, 只有一个活动符号表.

那么怎么理解活动符号表和符号表呢?

对于PHP来说, 当前活动的符号表是保存在全局变量EG(active_symbol_table)中的, 而于此同时, 还有个全局符号表保存在EG(symbol_table)中, 在进入一个函数调用的执行体之前, 会生成一个新的active_symbol_table, 并且会保持一个调用栈式样的符号表栈:EG(symtable_cache), 以便在退出函数调用的时候, 恢复之前的活动符号表(作用域).

同时在PHP中, 不能实现作用域继承, 也就是不能直接访问作用域外层的符号(需要加上golbal声明), 而如果加上global的声明的话, 也会在当前的活动作用域生成一个copy, 也就是说, 不存在在当前作用域可见的符号是保存在全局符号表的.

如上分析, 我们只需要在当前的活动符号表中, 就可以找到我们需要的变量的名称,

当然, 有了这些还不够, 我们如何在PHP的脚本中实现获取当前的符号表呢?

  get_defined_vars
 

然而有一个问题要注意, 就是get_defined_vars返回的是当前活动符号表中定义的变量名, 也就是说, 如果你需要包装一个函数, 类似于:

  get_variable_name($var)

并且尝试在这个函数中通过get_defined_vars来获取在调用get_variable_name时刻的符号表是行不通的.

所以, 我们获取变量名字的函数, 应该是下面的这个样子:

  get_variable_name($var, $scope)

现在, 已经得到了当前活动的符号表, 接下来, 如何得到变量的名字呢?

显然, 我们需要根据变量的值去查询这个表, 找到值等于要找值的变量, 但是, 这样做又有一个问题, 那就是, 可能会有多个变量的值相等啊?

所以, 我们需要给这个变量一个唯一值. 而要是想要这个变量, 那么, 我们的这个目的函数的形式又要变一下了:

  get_variable_name(&$var, $scope)

接下来完善这个函数体吧:

function get_variable_name(&$var, $scope = NULL) {
       if (NULL == $scope) {
          $scope = $GLOBALS;
       }

       $tmp  = $var;

       $var   = "tmp_exists_" . mt_rand();

       $name = array_search($var, $scope, TRUE);

       $var   = $tmp;

       return $name;
}

另外, 有一个问题就是, 如果有多个变量之间有引用, 那么这个函数只是返回最先定义的变量名..

另外, 你也可以参考: http://php.net/manual/en/language.variables.php

关于作用域, 你也可以参看我之前的文章: 深入理解PHP原理之变量作用域(Scope in PHP)


分享到:



Related Posts:

Tags: , ,

19 Responses to “如何获取一个变量的名字”

  1. 风雪之隅-鸟哥文章汇总 | 互联网菜鸟 |

    [...] 08 Dec 10 如何获取一个变量的名字 [...]

  2. Anonymous |

    当前 符号表不是 global 时
    $var = “tmp_exists_” . mt_rand();

    无法 改变 $scope 里面的值

    PHP Version 5.4.16

  3. PHP的Calling Scope | 午后小憩 |

    [...] 如何获取一个变量的名字 [...]

  4. skyinghua |

    自己跑跑代码就知道了

  5. zerox |

    你好,对于函数体有两个地方不明白,希望能给个小的demo解答一下:
    1、第一个参数 &$var 应该传递什么进去
    2、$var = “tmp_exists_” . mt_rand(); 这句是什么意思?

    谢谢!

  6. HillTop |

    大哥,能不能给我推荐一点中高级的书籍啊!

  7. 如何获取一个变量的名字 | 万维网黑客联盟 |

    [...] 本文地址: http://www.laruence.com/2010/12/08/1716.html [...]

  8. 132CC.com » Blog Archive » 如何获取一个变量的名字 |

    [...] 本文地址: http://www.laruence.com/2010/12/08/1716.html [...]

  9. Thinking In LAMP Blog » Blog Archive » PHP每月通讯(2011年1月) |

    [...] http://www.laruence.com/2010/12/08/1716.html 如何获取一个变量的名字 [...]

  10. wclssdn |

    我也没太理解… 你举的例子是说姓名和年龄. 那如果需要姓名年龄电话这三个, 查询字符串应该怎么写? 迷糊……..

  11. soulfree |

    好文章,前段时间正好研究这个问题.

  12. Shiwei Hu |

    Hi,

    话说,我以为。。。如果你要找到那个laruence的话,是不是直接遍历$_REQUEST好一点?或者说,你设置了laruence=27,如何在服务器端就知道你要的是laruence而不是别的呢?
    可能我没有理解你的文章,再研究研究。。。

  13. 雪候鸟 |

    @rzhome 好问题,,,,哈哈,,真是好问题… 其实我是为了引出这个问题,,现在看起来,这个假设有点问题,,鸡和蛋的问题…

  14. rzhome |

    菜鸟来学习了
    我想知道laruence=27做为query string提交给服务器的处理脚本
    调用get_variable_name(&$var, $scope)函数时$var的值如何取得呢?

  15. reeze |

    @fifsky
    php里有个方法天生就是干这个的 http://php.net/extract, 一般php的模版引擎都是用这个方法实现的。

    BTW: 刚好前一阵也想过过获取变量名的问题,贴个链结也凑下热闹:) http://reeze.cn/2010/10/30/php-internal-how-to-get-variables-name-an-extension-implement/

  16. fifsky |

    前几天写框架的时候还想过这个问题,之前的大部分框架在Controller给View传值的时候都是采用
    $this->assign(‘abc’,$abc);
    我就想,为什么不是$this->assign($abc);然后View层自动得到变量的名称abc还原成$abc呢?
    当时找到采用遍历$GLOBALS的方式,后来打印了一下$GLOBALS,发现这个数组还是很大的,其结果得不偿失,后来就放弃了

  17. 雪候鸟 |

    @jaceju :) 我忘了写个例子了

  18. jaceju |

    忘了 get_defined_vars() 可以在 function 裡用,可以把它的結果當成 $scope 的值,就可以取得 function 裡的變數名了…

  19. jaceju |

    請教您,如果不是 Global 的變數,那麼 $scope 該怎麼指定?

Leave a Reply

*