2011-12-05 39 views
3

我希望我的函數專門訪問外部變量 - 從其父函數。但是,使用global關鍵字設置的範圍太寬;我需要限制它。我如何獲得這個代碼來吐出'Level 2'而不是'Level 1'?我需要上課嗎?如何從父函數的作用域訪問變量?

<?php 
$a = "Level 1"; 

function first() { 
    $a = "Level 2"; 

    function second() { 
     global $a; 
     echo $a.'<br />'; 
    } 

    second(); 
} 

first(); 
//outputs 'Level 1' 
?> 

回答

9

PHP沒有嵌套函數或範圍的概念,嵌套函數的做法很糟糕。會發生什麼是PHP只是遇到一個函數聲明並創建一個正常的函數second。如果您嘗試再次調用first,則PHP將再次遇到second的函數聲明並崩潰,因爲函數second已被聲明。因此,不要在函數內聲明函數。

至於傳遞值,或者明確地將它們作爲函數參數傳遞,或者如您所說,創建類(如果有意義的話)

+0

啊哈!感謝您的教育答案。這很有道理,你解釋得很好。我會嘗試函數參數路由。 –

+0

也可以防禦性地檢查'if(function_exists('second')){} – WraithKenny

25

只是爲了舉例起見,如果我理解你想要做什麼,你可以使用一個closure(PHP 5.3+),爲「閉包也可以繼承父範圍變量」與use關鍵詞。

$a = "Level 1"; 

function first() { 
    $a = "Level 2"; 

    $func = function() use ($a) { 
     echo $a.'<br />'; 
    }; 

    $func(); 
} 

first(); 
// prints 'Level 2<br />' 

閉包最常用於回調函數。但是,這可能不是使用最佳方案。正如其他人所建議的,僅僅因爲你可以做點什麼並不意味着它是最好的主意。

+0

哇,你們很快。我會將此建議擱置以備將來參考。謝謝! –

+0

我還需要將數據傳入和傳出回調函數,所以我必須編寫'use(&$ a)'來通過引用傳遞它。 (記住preg_replace_callback場景中的匹配。) – ygoe