экспортировать переменную в предыдущую область в PHP - PullRequest
2 голосов
/ 22 августа 2010

Теперь, прежде чем прыгать о том, как не стоит смешивать области видимости, я это понимаю. Однако это тот случай, когда должно происходить либо смешивание области действия, либо значительное дублирование кода - ничего вокруг. И я бы предпочел смешение сфер.

Тем не менее, я хотел бы этот код:

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' ));

Тогда в шаблонах / 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 ]

6 голосов
/ 22 августа 2010

Вот почему у нас есть 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 голос
/ 22 августа 2010

Я только что запустил этот код

- 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'ом. То же самое с $ this.

** ОБНОВЛЕНИЕ **

Поскольку eval() является злом и его следует избегать (как любезно предлагается), здесь мы переписываем с использованием простых шаблонов. Таким образом, ваш дизайнер должен знать только доступное имя переменной (в спецификации):

- 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>
1 голос
/ 22 августа 2010

Невозможно сделать то, что вы просите, с учетом ограничений, которые вы налагаете.Там никогда не будет хорошей причины, чтобы делать именно то, что вы пытаетесь сделать.Есть много лучших решений.

В любом случае, самое близкое, что вы получите, это передача по ссылке:

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

function b()
{
  a($a, $b, $c);
}
?>
0 голосов
/ 22 августа 2010

Я не понимаю, почему вы не можете вернуть их в виде массива.Помимо предложения @NullUserException, я бы предложил следующий подход (если вы не выбираете маршрут ООП).

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

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

function b() {
  list($a, $b, $c) = a();
  echo $a . $b . $c;
}
0 голосов
/ 22 августа 2010

почему вы не можете вернуть $ 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

это не нарушает область видимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...