调用函数时,PHP保留作用域
我有一个函数,该函数包括基于传递给它的字符串的文件,即查询字符串中的操作变量。我将其用于过滤等目的,以便人们无法包含他们不应该包含的文件,如果文件不存在,则会加载默认文件。
问题在于,当函数运行并包括文件作用域时,由于include在函数内部运行而丢失。这成为一个问题,因为我使用了全局配置文件,然后为站点上的每个模块使用了特定的配置文件。
目前,我的操作方式是定义要用作全局变量的变量,然后将其添加到过滤功能的顶部。
有没有更简单的方法来做到这一点,即在进行函数调用时保留作用域,或者是否存在诸如PHP宏之类的东西?
编辑:最好使用extract($ _ GLOBALS);在我的函数调用里面?
编辑2:
对于任何关心的人。我意识到我已经完全考虑了这个问题,而不是使用一个函数,我应该只使用一个include,du!这样,我就可以保持自己的视野,也可以吃蛋糕。
解决方案
编辑:好的,我已经重新阅读了问题,我想我现在就知道我们在说什么:
我们想要这样的工作:
// myInclude.php $x = "abc"; // ----------------------- // myRegularFile.php function doInclude() { include 'myInclude.php'; } $x = "A default value"; doInclude(); echo $x; // should be "abc", but actually prints "A default value"
如果仅更改几个变量,并且提前知道将在include中定义哪些变量,请在doInclude()函数中将它们声明为global。
另外,如果每个include都可以定义任意数量的变量,则可以将它们全部放入一个数组中:
// myInclude.php $includedVars['x'] = "abc"; $includedVars['y'] = "def"; // ------------------ // myRegularFile.php function doInclude() { global $includedVars; include 'myInclude.php'; // perhaps filter out any "unexpected" variables here if you want } doInclude(); extract($includedVars); echo $x; // "abc" echo $y; // "def"
原始答案:
这种事情被称为"闭包",并在PHP 5.3中引入
http://steike.com/code/php-closures/
Would it be better to use extract($_GLOBALS); inside my function call instead?
亲爱的主,不。如果要从函数内部访问全局变量,只需使用global
关键字。例如:
$x = "foo"; function wrong() { echo $x; } function right() { global $x; echo $x; } wrong(); // undefined variable $x right(); // "foo"
当涉及到配置选项(尤其是文件路径等)时,我通常只使用define()使用绝对路径定义它们。就像是:
define('MY_CONFIG_PATH', '/home/jschmoe/myfiles/config.inc.php');
这样,无论范围变化如何,它们始终可以全局访问,除非我迁移到其他文件结构,否则它始终能够找到所有内容。
如果我理解正确,那么代码如下:
function do_include($foo) { if (is_valid($foo)) include $foo; } do_include(@$_GET['foo']);
一种解决方案(可能简单也可能不简单,具体取决于代码库)是将include移出全局范围:
if (is_valid(@$_GET['foo'])) include $_GET['foo'];
还存在其他解决方法(如我们提到的:声明全局变量,直接使用$ _GLOBALS数组等),但是此解决方案的优点是我们不必在所有包含的文件中都记住此类约定。
为什么不从包含中返回值,然后将包含调用的值设置为变量:
config.php
return array( 'foo'=>'bar', 'x'=>23, 'y'=>12 );
script.php
$config = require('config.php'); var_dump($config);
无需将全局变量弄乱
Is there any easier way to do this, i.e. by preserving scope when a function call is made
我们可以使用:
function doInclude($file, $args = array()) { extract($args); include($file); }
如果我们不想显式传递变量,则可以使用get_defined_vars
作为参数调用doInclude
,例如:
doInclude('test.template.php', get_defined_vars());
就我个人而言,我宁愿传递一个显式数组,而不是使用它,但是它将起作用。
我们可以将包含文件中的变量声明为全局变量,以确保它们具有全局范围:
//inc.php global $cfg; $cfg['foo'] = bar; //index.php function get_cfg($cfgFile) { if (valid_cfg_file($cfgFile)) { include_once($cfgFile); } } ... get_cfg('inc.php'); echo "cfg[foo]: $cfg[foo]\n";