2011-11-04 60 views
4

TL;博士:有沒有一種方法,以防止改動(主要鎖定)聲明/定義被包含的變量之前的include()呼叫,通過文件?此外,有點相關question保護變量「包括污染」在PHP


我想知道可以採取什麼措施,以避免包括文件中的可變污染。例如,給定這個奇特的小功能:

/** 
* Recursively loads values by include returns into 
* arguments of a callback 
* 
* If $path is a file, only that file will be included. 
* If $path is a directory, all files in that directory 
* and all sub-directories will be included. 
* 
* When a file is included, $callback is invoked passing 
* the returned value as an argument. 
* 
* @param string $path 
* @param callable $callback 
*/ 
function load_values_recursive($path, $callback){ 
    $paths[] = path($path); 
    while(!empty($paths)){ 
     $path = array_pop($paths); 
     if(is_file($path)){ 
      if(true === $callback(include($path))){ 
       break; 
      } 
     } 
     if(is_dir($path)){ 
      foreach(glob($path . '*') as $path){ 
       $paths[] = path($path); 
      } 
     } 
    } 
} 

我知道它缺少一些類型檢查和其他的解釋,讓我們忽略這些。

不管怎麼說,該函數基本上是通過一串「數據」文件僅僅返回值進行篩選,(通常配置陣列或路由表,但無論),然後調用傳遞迴調使得該值可以被過濾或以某種方式排序或使用。例如:

$values = array(); 
load_values_recursive('path/to/dir/', function($value) use(&$values){ 
    $values[] = $value; 
}); 

而且path/to/dir/可能遵循此模板的幾個文件:

return array(
    // yay, data! 
); 

我的問題是當這些「配置」文件(或什麼的,想保持這種便攜式和交叉功能)開始包含甚至基本的邏輯。總是有可能污染功能本地的變量。例如,一個配置文件,對於聰明的緣故呢:

return array(
    'path_1' => $path = 'some/long/complicated/path/', 
    'path_2' => $path . 'foo/', 
    'path_3' => $path . 'bar/', 
); 

現在,鑑於$path恰好是可見相對於當前的目錄中,該功能要去靠不住:

// ... 
if(is_file($path)){ 
    if(true === $callback(include($path))){ // path gets reset to 
     break;        // some/long/complicated/path/ 
    } 
} 
if(is_dir($path)){       // and gets added into the 
    foreach(glob($path . '*') as $path){ // search tree 
     $paths[] = path($path); 
    } 
} 
// ... 

這可能會有最糟糕的結果。唯一1解決方案,我能想到的,是包裹include()呼叫另一個匿名函數來改變範圍:從引起副作用

// ... 
if(true === call_user_func(function() use($callback, $path){ 
    return $callback($path); 
})){ 
    break; 
} 
// ... 

因此保護$path更重要的是,$callback)每次迭代。

我想知道在這種情況下是否存在一種更簡單的方式來鎖定PHP中的變量。

  1. 我只是想在這裏的記錄;我知道我可以使用例如elseif來緩解特定於此功能的問題之一,但是我的問題更關注環境不可知的解決方案,如果您願意的話,這是一個全面的解決方案。
+0

命名空間不會解決您的問題?自5.3 PHP的悲慘命名空間變得更好和可用...幾乎沒有。 –

+0

@edem - 雖然我充分利用了大多數可用的5.3+功能,但名稱空間是我沒有采用的名稱空間;我無法想象在這種情況下這將如何幫助。 – Dan

+0

什麼是最近所有的** TL;博士:**參考最近? –

回答

1

我用以下解決方案去包括污染:

$value = call_user_func(function(){ 
    return include(func_get_arg(0)); 
}, $path); 

$path是無處在列入待觀察,它似乎最優雅的。當然,從包含文件調用func_get_arg($i)將產生通過的值,但是,以及...

+0

我收到了一個** - 1 **這個答案和另一個使用類似的方法來回答這個問題http://stackoverflow.com/a/8376780/409279;我只是假設它來自同一個人。你願意詳細說明爲什麼嗎?我很好奇一個更好的選擇,當然你必須知道一個。 – Dan

+0

顯然來自beelzebub,因爲你是一個現代日! – lol

+1

@lol現在,downvotes現在不管了:-) – Dan

1

看看Giving PHP include()'d files parent variable scope它必須能夠在此處使用的問題相當獨特的方法。

它相當於在包含之前取消設置所有定義的變量,然後重置它們。

它當然不是優雅的,但它會工作。

+0

謝謝@Allain Lalonde - 是的,這是我考慮過的;到目前爲止,最優雅的解決方案就是我以前使用過很多次的解決方案;也就是說,無論在自我調用匿名函數中創建一個新的作用域,還是使用「use()」。我想我以前可能問過一個問題,詢問是否可以取消同時用作include()的參數的$ path變量,但無濟於事。這似乎是唯一的選擇。 – Dan