PHP从一个类包含的文件访问变量
写这个问题时,我已经解决了我的问题,但我仍然有其他问题。基本上我想我在这里有变量的范围理解问题,但目前我不明白为什么这不起作用。有人可以为我指出吗?PHP从一个类包含的文件访问变量
我有这样的index.php中:
spl_autoload_register(function($class) { include_once("./Class/{$class}.php")); });
Site::Page("page");
的Site.php包含一个类中,调用的方法主要包括另一个文件:
class Site {
public static function Page($name = null) {
if ($name) $inc = @include_once("./Page/{$name}.php");
}
public static function Dialog($name = null) {
if ($name) $inc = @include_once("./Page/Dialogs/{$name}.php");
}
}
page.php文件包含此:
$DB = DB::GetInstance();
Site::Dialog("dialog");
and dialog.php contains this:
$Stuff = $DB->Query("Some SQL query here");
if ($Stuff) {
// Processing result
}
我遇到的问题是PHP给了我有关$ DB的错误,因此它无法调用dialog.php中的Query方法。我预计它是全球可用的,因为我只是包含另一个文件,但显然情况并非如此。
DB类是一个管理数据库连接的单例对象,我用dialog.php中的另一行解决了问题,我再次调用GetInstance()并将其分配给$ DB。
但是如果我想从index.php获得另一个(而不是单例)类实例,例如?我怎样才能访问它,为什么这种方法不工作?
你说得对,这是一个关于可变范围的问题。使用静态方法来访问你的类,你不会有这个问题,因为静态方法是全局可用的。
但是,如果您想使用不是从静态方法获取的变量,那么您需要做更多的工作。我能想到的最简单的解决方案是传递一个包含变量的数组。
public static function import($file, array $variables = [])
{
if(!file_exists($file)) {
throw new RuntimeException('Cannot find file: ' . $file);
}
extract($variables); // <- This is important
include $file;
}
extract()
函数接受一个关联数组。数组键然后被转换成变量标识符/名称,并且相应的值是变量值。您现在可以访问任何传递的变量。
但也有它公平的问题。要了解的最重要的问题是本地定义的变量被覆盖的机会。默认情况下,extract()
直接将所有变量导入当前范围。想象一下,在调用extract()
之前定义了一个名为$user
的变量,并且extract()
函数接收到一个名为user
的键的数组。原来的$user
变量将被覆盖,并且存储在其中的任何值都将丢失。这可能会导致严重的错误。
但也有解决方案。 extract()
函数也需要flags,它告诉它如何在范围内定义新的变量。我会使用名为EXTR_PREFIX_ALL
的国旗。这可以确保所有提取的变量都以事先知道的名称作为前缀。
extract($variables, EXTR_PREFIX_ALL, 'prefix_');
现在,当您使用的方法import()
,你可以做到以下几点:
Site::import('filename.php', [
'db' => DB::getInstance()
]);
// Inside: filename.php
$stuff = $prefixed_db->query('...');
希望这有助于编码快乐。
奖金信息:
注意extract()
也有安全问题。如果传递的数组包含来自客户端/用户的输入,那么恶意用户可能会覆盖脚本中的重要变量。想象一下,恶意用户覆盖从false
到true
的变量$loggedin
。他现在通过利用extract()
访问您的禁区。只要前缀是唯一的,前缀标志有助于缓解这种情况。
我想'Site :: Page(“page”);'调用'page.php'文件。替换'spl_autoload_register(function($ class){include_once(“./ Class/{$ class} .php”)); }); Site :: Page(“page”);'带'Site :: Page(“page”); (函数($ class){include_once(“./ Class/{$ class} .php”)); });' –