2015-08-08 70 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()訪問您的禁區。只要前綴是唯一的,前綴標誌有助於緩解這種情況。