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

时间:2013-07-13 22:14:50

标签: php class hook eval

(如果你喜欢挑战。请投票提出这个问题。)

亲爱的stackoverflow研究员。我想为钩子/扩展提供一种出色的方式。

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

问题式:

  1. 我不想将局部变量转换为全局变量。如果他们是本地人,他们应该留在当地。
  2. 我不知道hook-developer想要访问哪些变量,所以我无法将任何选定的变量引用传递给hook。
  3. 钩子只能访问嵌套在外部的全局变量,这使得在父本地范围内调用钩子毫无价值。
  4. 静态虚拟钩子示例(没有任何动态):

    <?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

2 个答案:

答案 0 :(得分:0)

到目前为止,谁可以提出比这更好的解决方案?它不使用引用,而是使用可变重复项。但它足够接近并且在嵌套变量范围内消除了对钩子的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();
?>

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

答案 1 :(得分:-1)

使用你的示例函数,我能够得到hook-&gt; before_process()来修改$ couldbeanything变量 - 即使它是从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'。

关键是在$ foobar()函数中使$ canbeanything成为一个全局变量 - 这个函数和钩子类中的before_process()函数都修改了相同的全局变量。

另一个选项,如果你想保留两个值,就是让$ couldbeanything成为一个数组。

$ couldbeanything = 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 is“hello world”,而Hook则是“hello dummy”。'

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

$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.'"';

这将返回'本地值为“hello world”,而钩子修改值为“原始值 - 增值”。全球价值是“原始价值”'