将变量导出到PHP中的上一个范围

时间:2010-08-22 00:46:11

标签: php scope

现在,在你跳过如何不应该混合范围之前:我意识到这一点。但是,这种情况下必须进行范围混合或必须发生主要代码重复 - 周围没有任何内容。而且我更喜欢范围混合。

那就是说,我想要这段代码:

function a() {
    $a = "a";
    $b = "b";
    $c = "c";
}
function b() {
    a();
    echo $a . $b . $c;
}
b(); // Output: abc
echo $a; // Should raise a notice that $a is undefined

能够作为评论工作。我知道在大多数语言中都不可能 - 我能用Ruby做到这一点;并且想知道你是否可以用PHP做到这一点。

在实际情况下,事先不知道变量的名称。

再一次,这是代码重复或者这个 - 绝对没办法。

此外,如果a必须是a('b')之类的东西,那也没关系。


实际上,代码是这样的:

static function renderError($what, $vararray) {
    foreach($vararray as $key => $val) { /* this foreach is the code we want to decouple */
        $key = 'e_'.$key;
        $$key = htmlspecialchars($val);
    }
    ob_clean();
    exit(eval('?>'.file_get_contents(ROOT."/templates/$what.php")));
}

通过E_Render::renderError('NotFound', array( 'requested_url' => '/notfound', 'misspelling' => '/reallynotfound' ));

之类的通话

然后,在templates / NotFound.php中,你会有类似的东西:

<html>
<body>
<?php echo $e_requested_url; ?> could not be found. Did you mean <?php echo $e_misspelling: ?>?
</body>
</html>

我们真的不希望我们的模板作者做更多的事情......如果没有更好的可用,$e['requested_url']就可以完成。

5 个答案:

答案 0 :(得分:6)

这就是为什么我们有OO:

class Foo {

    function a() {
        $this->a = "a";
        $this->b = "b";
        $this->c = "c";
    }

    function b() {
        $this->a();
        echo $this->a . $this->b . $this->c;
    }
}

$f = new Foo;
$f->b(); // Output: abc
echo $a; // Should raise a notice that $a is undefined

可替换地:

function a() {
    $a = "a";
    $b = "b";
    $c = "c";

    return compact('a', 'b', 'c');
}

function b() {
    extract(a());
    echo $a . $b . $c;
}

请参阅:compact()extract()

否则,如果不彻底改变语言,我就没有办法做到这一点。

PS:如果您认为此功能如此重要,为什么不使用Ruby?

答案 1 :(得分:1)

鉴于你施加的限制,没有办法做你所要求的。完全没有理由去做你想做的事情。有很多更好的解决方案。

无论如何,你得到的最接近的是参考:

<?php
function a(&$a, &$b, &$c)
{
  $a = 1;
  $b = 2;
  $c = 3;
}

function b()
{
  a($a, $b, $c);
}
?>

答案 2 :(得分:1)

我刚刚运行了这段代码

- var1.php

<?php

function a($vars) {
   foreach ($vars as $var => $val) {
      $$var = $val;
   }

   echo eval('?>' . file_get_contents('var2.php') . '<?php ');
};


a(array('a' => 'foo', 'b' => 'bar', 'c' => 'baz'));

- var2.php

<html>
   <body>
      <div><?= '$a = "' . $a . '"' ?></div>
      <div><?= '$b = "' . $b . '"' ?></div>
      <div><?= '$c = "' . $c . '"' ?></div>
   </body>
</html>

它输出:

$a = "foo"
$b = "bar"
$c = "baz"

原因是,由于eval()保持当前范围,因此在函数内部本地声明的任何变量也将在eval'ed字符串内部可用。 $ this也一样。

** 更新 **

由于eval() evil 并且应该避免(如同所建议的),这里是使用简单模板重写。这样,您的设计师只需知道可用的变量名称(在规范中):

- var1.php

<?php

function showError($error, $vars) {

   $template = file_get_contents("{$error}.php");
   $keys = array();
   $values = array();
   foreach ($vars as $var => $val) {
      $keys[] = '@{e_'.$var.'}';
      $values[] = $val;
   }

   echo str_replace($keys, $values, $template);
};

showError('template1', array('value' => 300, 'message' => 'Something foo'));

- template1.php

<html>
   <body>
      <div>Error <span style="font-weight: bold; color: red;">@{e_value}</span></div>
      <div>The message was : <em>@{e_message}</em></div>
   </body>
</html>

答案 3 :(得分:0)

为什么你不能从()返回$ a?

function a() {
    $a = "a";
    return $a;
}
function b() {
    $a = a();
    echo $a;
}
b(); // Output: a
echo $a; // Should raise a notice that $a is undefined

这不会打破范围。

答案 4 :(得分:0)

我不明白为什么你不能把它们作为数组返回。除了@NullUserException给你的建议,我建议采用以下方法(如果你不采用OOP路线)。

function a() {
  $a = "a";
  $b = "b";
  $c = "c";

  return array($a, $b, $c);
}

function b() {
  list($a, $b, $c) = a();
  echo $a . $b . $c;
}