2015-08-08 74 views
0

写这个问题时,我已经解决了我的问题,但我仍然有其他问题。基本上我想我在这里有变量的范围理解问题,但目前我不明白为什么这不起作用。有人可以为我指出吗?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获得另一个(而不是单例)类实例,例如?我怎样才能访问它,为什么这种方法不工作?

+0

我想'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”)); });' –

回答

0

你说得对,这是一个关于可变范围的问题。使用静态方法来访问你的类,你不会有这个问题,因为静态方法是全局可用的。

但是,如果您想使用不是从静态方法获取的变量,那么您需要做更多的工作。我能想到的最简单的解决方案是传递一个包含变量的数组。

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()也有安全问题。如果传递的数组包含来自客户端/用户的输入,那么恶意用户可能会覆盖脚本中的重要变量。想象一下,恶意用户覆盖从falsetrue的变量$loggedin。他现在通过利用extract()访问您的禁区。只要前缀是唯一的,前缀标志有助于缓解这种情况。