代码之家  ›  专栏  ›  技术社区  ›  John J. Camilleri

如何在调用者作用域中设置变量,如extract()函数

  •  2
  • John J. Camilleri  · 技术社区  · 14 年前

    我知道直接在caller的范围内设置变量可能不是一个好主意。 extract() 函数就是这么做的!我想写我自己版本的 但却不知道如何在调用者中设置变量。有什么想法吗? 我最接近的方法就是修改来电者的电话号码 args 使用 debug_backtrace() ,但这不是一回事。。。

    4 回复  |  直到 10 年前
        1
  •  3
  •   Paul Dixon    14 年前

    不能在父作用域中修改局部变量-extract()使用的方法不会被PHP公开。

    另外,您从debug\u stacktrace()得到的信息并没有神奇地链接到真正的堆栈。你不能修改它,希望你的修改是活的!

        2
  •  1
  •   Artefacto    14 年前

    您只能在PHP扩展中完成。如果调用内部PHP函数,它将不会在新的PHP作用域中运行(即,不会创建新的符号表)。因此,您可以通过更改全局范围来修改“父范围” EG(active_symbol_table) .

    extract 其核心是:

    if (!EG(active_symbol_table)) {
        zend_rebuild_symbol_table(TSRMLS_C);
    }
    //loop through the given array
    ZEND_SET_SYMBOL_WITH_LENGTH(EG(active_symbol_table),
        Z_STRVAL(final_name), Z_STRLEN(final_name) + 1, data, 1, 0);
    

    不过,也有一些细微差别。看到了吗 implementation of extract 提取 有没有办法处理它接受的几种选择。

        3
  •  1
  •   hardcoder    12 年前

    是的,我知道滥用$GLOBAL范围是肮脏的,但是嘿,我们是来解决问题的,不是吗?:)

    function set_first_name($firstname) {
        /* check if $firstname is defined in caller */
        if(array_key_exists('firstname', $GLOBALS)) {
            $firstname_was = $GLOBALS['firstname'];
        } else {
            $firstname_was = 'undefined';
        }   
    
        /* set $firstname in caller */
        $GLOBALS['firstname'] = $firstname;
    
        /* show onscreen confirmation for debugging */
        echo '<br>firstname was ' . $firstname_was . ' and now is: ' . $firstname;
    }  
    
    set_first_name('John');
    
    set_first_name('Michael');
    

    函数返回以下输出:

        <br>firstname was undefined and now is: John
        <br>firstname was John and now is: Michael
    
        4
  •  0
  •   Community datashaman    4 年前

    这取决于你有多需要这么做。如果只是为了源美,那就另辟蹊径。如果,出于某种原因,你 真正地 要搞乱父作用域,总有办法的。

    使用提取本身

    function backwardNames($x) {
        $out = [];
        foreach($x as $key=>$val) {
            $rev = strrev($key);
            $out[$rev] = $val;
        }
        return $out;
    }
    
    extract(backwardNames($myArray));
    

    这里没有魔法。

    解决方案2

    提取 是的,使用 评估 变量输出 不会出错的

    function makeMyVariables() {
        $vars = [
            "a" => 4,
            "b" => 5,
        ];
        $out = var_export($vars,1);
        $out = "extract(".$out.");";
        return $out;
    }
    
    eval(makeMyVariables());   // this is how you call it
    // now $a is 4, $b is 5
    

    然而,事实上, 一个电话也做不到。