1

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

亲爱的stackoverflow伙伴。我想为钩子/扩展提供一个绝妙的方法。

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

问题:

  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

4

2 回答 2

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();
?>

查看钩子类,以及我如何在 foobar() 中执行钩子。

于 2013-07-14T00:14:11.703 回答
-1

使用您的示例函数,我能够获取 hook->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();

这将返回“你好假人”。

关键是让 $couldbeanything 成为 foobar() 函数中的全局变量——这样钩子类中的函数和 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 是“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”,而挂钩修改值是“原始值 - 附加值”。全球价值是“原始价值”'

于 2013-07-13T22:27:54.363 回答