(如果你喜欢一个好的挑战。投票给这个问题。)
亲爱的斯塔克夫弗洛伙伴们。我想为钩子/扩展提供一种绝妙的方式。
访问类或函数外部的变量引用时遇到问题。
问题:
- 我不想把局部变量变成全局变量。如果他们是当地人,他们应该留在当地
- 我不知道钩子开发人员想要访问什么变量,所以我不能将任何选定的变量引用传递给钩子
- 钩子只能访问嵌套在其自身外部的全局,这使得在父本地作用域中调用钩子变得毫无价值
静态假钩示例(没有任何动力学):
<?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",而钩子修改后的值是"原始值-附加值"。全局值为"原始值"的