2008-10-03 97 views
5

我有一個函數,它包含基於傳遞給它的字符串的文件,即查詢字符串中的操作變量。我使用這個過濾目的等,所以人們不能包括他們不應該能夠的文件,如果文件不存在,而是加載默認文件。 問題是,當函數運行幷包含文件範圍時,由於包含在函數內部運行而丟失。這成爲一個問題,因爲我使用全局配置文件,然後我爲站點上的每個模塊使用特定的配置文件。 我現在做的方式是定義我希望能夠用作全局變量的變量,然後將它們添加到過濾函數的頂部。PHP調用函數時保留範圍

有沒有更簡單的方法來做到這一點,即通過保存函數調用時的範圍或者是否存在PHP宏這樣的事情?

編輯:它會更好使用提取物($ _ GLOBALS);在我的函數調用呢?

編輯2: 對於任何關心的人。我意識到我完全在想這個問題,而不是使用一個函數,我應該只使用一個include,呵呵!這樣我就可以保留我的範圍,並擁有我的蛋糕。

+0

在我的情況下訴諸你的「編輯2」,只是使用包括沒有工作,因爲我有更多的東西在繼續。基本上認爲它是一個「視圖」類,它需要一個viewscript.php,因爲我們在插件範圍內,我想將「全局」範圍傳遞給視圖,而不需要將每個變量都聲明爲全局的「 doInclude「功能。 – 2013-02-23 23:15:15

回答

5

編輯:好吧,我重新閱讀你的問題,我覺得我得到你現在在說什麼:
你想是這樣工作的:

// myInclude.php 
$x = "abc"; 

// ----------------------- 
// myRegularFile.php 

function doInclude() { 
    include 'myInclude.php'; 
} 
$x = "A default value"; 
doInclude(); 
echo $x; // should be "abc", but actually prints "A default value" 

如果您只是改變了幾個變量,並且您事先知道包含中將定義哪些變量,將其聲明爲函數中的global

另外,如果您的每一個包括可以定義任意數量的變量,你可以把他們都變成一個數組:

// myInclude.php 
$includedVars['x'] = "abc"; 
$includedVars['y'] = "def"; 

// ------------------ 
// myRegularFile.php 
function doInclude() { 
    global $includedVars; 
    include 'myInclude.php'; 
    // perhaps filter out any "unexpected" variables here if you want 
} 

doInclude(); 
extract($includedVars); 
echo $x;  // "abc" 
echo $y;  // "def" 

原來的答案:

這樣的事情被稱爲「封閉」,並正在推出PHP 5.3中的版本。

http://steike.com/code/php-closures/

使用extract($ _ GLOBALS)會更好嗎?在我的函數調用呢?

親愛的主,沒有。如果要從函數內部訪問全局變量,只需使用global關鍵字。例如:

$x = "foo"; 
function wrong() { 
    echo $x; 
} 
function right() { 
    global $x; 
    echo $x; 
} 

wrong();  // undefined variable $x 
right();  // "foo" 
+0

這正是我遇到的問題。我試圖爲腳本開發一個插件,但不幸的是,這個腳本使用全局變量來做一些奇怪的事情。跟蹤所有我需要的各種全局變量並在「doInclude」函數中聲明它們是一件很痛苦的事情。噢,我認爲$ GLOBALS會起作用,但是由於功能和順序的順序,這不起作用。我猜這就是插件開發人員的生活。 – 2013-02-23 23:12:34

0

當涉及到的配置選項(特別是文件路徑和例如)一般我只使用一個限定與絕對路徑定義它們()。喜歡的東西:

define('MY_CONFIG_PATH', '/home/jschmoe/myfiles/config.inc.php'); 

這樣,他們總是全局訪問,無論範圍的變化,除非我遷移到不同的文件結構,它總是能找到的一切。

+0

我有這種方式設置的大部分配置變量,但我有國家代碼數組,數據庫對象等,不能用這種方式定義。 – Joshua 2008-10-03 05:32:16

0

如果我理解正確的話,你必須沿着線代碼:

function do_include($foo) { 
    if (is_valid($foo)) 
    include $foo; 
} 

do_include(@$_GET['foo']); 

一個解決方案(這可能會或可能不會是簡單的,根據不同的代碼庫)是移動在全球包括了範圍:

if (is_valid(@$_GET['foo'])) 
    include $_GET['foo']; 

其他解決方法存在(如你所提到的:聲明全局變量,用$ _GLOBALS陣列直接等工作),但這種解決方案的好處是,你不必記住所有這些公約包含的文件。

0

爲什麼不返回一個值從包括然後設置包括呼叫到一個變量的值:

的config.php

return array(
    'foo'=>'bar', 
    'x'=>23, 
    'y'=>12 
); 

的script.php

$config = require('config.php'); 
var_dump($config); 

無需要搞亂全局變量的地方

0

有沒有做到這一點,通過保護範圍,即任何更簡單的方法,當一個函數調用時

你可以使用:

function doInclude($file, $args = array()) { 
    extract($args); 
    include($file); 
} 

如果你不想明確地傳遞變量,你可致電doIncludeget_defined_vars作爲參數,如:

doInclude('test.template.php', get_defined_vars()); 

個人而言,我寧願傳遞一個明確的陣列,而不是利用這一點,但它會工作。

+0

這不是回答這個問題,而是說「你做錯了。」謝謝史蒂夫。有時候會出現這樣的情況,它會很好地運行一個使用所需範圍的函數(即全局)`call_user_func_array_with_scope('function',$ args,$ this)`如果它存在的話它會很漂亮......(或者傳遞「 null「或全局性的,以便將其反彈到全局範圍內。當在一些明確定義的約束條件下構建一個插件來工作時,它會派上用場。 – 2013-02-23 23:20:09

0

可以聲明包含的文件爲全局中的變量,以確保他們有全局範圍:

//inc.php 
global $cfg; 
$cfg['foo'] = bar; 

//index.php 
function get_cfg($cfgFile) { 
    if (valid_cfg_file($cfgFile)) { 
     include_once($cfgFile); 
    } 
} 
... 
get_cfg('inc.php'); 
echo "cfg[foo]: $cfg[foo]\n";