访问本地范围之外的PHP变量引用


Accessing PHP variable references outside the local scope

(如果你喜欢一个好的挑战。投票给这个问题。)

亲爱的斯塔克夫弗洛伙伴们。我想为钩子/扩展提供一种绝妙的方式。

访问类或函数外部的变量引用时遇到问题。

问题:

  1. 我不想把局部变量变成全局变量。如果他们是当地人,他们应该留在当地
  2. 我不知道钩子开发人员想要访问什么变量,所以我不能将任何选定的变量引用传递给钩子
  3. 钩子只能访问嵌套在其自身外部的全局,这使得在父本地作用域中调用钩子变得毫无价值

静态假钩示例(没有任何动力学):

<?php
  class hook {
    function before_process() {
      global $couldbeanything;
      $couldbeanything = 'hello dummy';
    }
  }
?>

在全球范围内工作:

<?php
  $couldbeanything = 'hello world';
  $hook = new hook;      
  $hook->before_process();
  echo $couldbeanything;
?>

在函数中不起作用(本地范围):

<?php
  function foobar() {
    $couldbeanything = 'hello world';
    $hook = new hook;      
    $hook->before_process();
    echo $couldbeanything;
  }
  foobar();
?>

我实际上需要这样的东西在钩子里(如果有这样的东西的话):

parent $couldbeanything;

outer $couldbeanything;

我能想到的唯一解决方案是PunBB使用的eval(php_code_from_an_xml_doc)。它也有缺点。如果不说明要访问的外部引用,您可能会意外地用相同的名称覆盖变量。此外,经过评估的XML格式的PHP代码调试起来有点俗气。

谁是这里最聪明的人,拥有比eval()更好的解决方案。

也许这些是一些想法的工具:get_defined_vars、extract、pass-by-reference、call_user_func

到目前为止,谁能想出比这更好的解决方案?它不使用引用,而是使用变量重复项。但它已经足够接近了,并且消除了嵌套变量范围中挂钩的eval()的需要。

<?php
  class hook {
    function before_process($args) {
      extract($args);
      $couldbeanything = 'good bye world';
      return compact('couldbeanything');
    }
  }
  function foobar() {
    $couldbeanything = 'hello world';
    $hook = new hook;
    extract($hook->before_process(get_defined_vars()), EXTR_OVERWRITE);
    echo $couldbeanything;
  }
  foobar();
?>

请参阅钩子类,以及如何在foobar()中执行钩子。

使用您的示例函数,我能够获得hook->before_process()来修改$couldbeanthing变量,即使它是从foobar()函数中调用的。这是你的目标吗?

$couldbeanything=NULL;
class hook {
    function before_process() {
      global $couldbeanything;
      $couldbeanything = 'hello dummy';
    }
  }

  function foobar() {
      global $couldbeanything;
    $couldbeanything = 'hello world';
    $hook=new hook;
    $hook->before_process();
    echo $couldbeanything;
  }
  foobar();

这将返回"hello-dummy"。

关键是使$couldbeanthing成为foobar()函数中的全局变量——这样,该函数和hook类中的before_process()函数都在修改同一个全局变量。

如果您想保留这两个值,另一种选择是使$couldbeanthing成为一个数组。

$couldbeanthing=NULL;

class hook {
    function before_process() {
      global $couldbeanything;
      $couldbeanything['hook'] = 'hello dummy';
    }
  }

  function foobar() {
      global $couldbeanything;
    $couldbeanything['foobar'] = 'hello world';
    $hook=new hook;
    $hook->before_process();
    echo'Foobar is "'.$couldbeanything['foobar'].'", while Hook is "'.$couldbeanything['hook'].'".';
  }
  foobar();

返回‘Foobar是"你好世界",而Hook是"你好假人"。’

否则,为了不更改全局变量,这将起作用:

$couldbeanything='Original Value';
class hook {
    function before_process() {
      global $couldbeanything;
      $newValue=$couldbeanything.' - added value';
      return $newValue;
    }
  }

  function foobar() {
    $couldbeanything = 'hello world';
    $hook=new hook;
    $newValue=$hook->before_process();
    echo'The local value is "'.$couldbeanything.'", while the hook modified value is "'.$newValue.'". ';
  }
  foobar();
echo'Global value is "'.$couldbeanything.'"';

这将返回"本地值是"helloworld",而钩子修改后的值是"原始值-附加值"。全局值为"原始值"的