2010-08-24 32 views
6

作爲Web開發人員,我一直在使用這種方法有點像一個登錄表單或其他的「保存」操作(忽略直接訪問輸入變量的危險):有什麼辦法可以動態訪問超全球?

if (isset($_POST['action']) && $_POST['action'] == 'login') 
{ 
    // we're probably logging in, so let's process that here 
} 

爲了讓這個不那麼單調乏味和保持與DRY原則(排序)行,我做這件事:

function isset_and_is ($superglobal, $key, $value) 
{ 
    $ref = '_' . strtoupper($superglobal); 

    return isset($$ref[$key]) && $$ref[$key] == $value; 
} 

if (isset_and_is('post', 'action', 'login')) 
{ 
    // we're probably logging in, so let's process that here 
} 

這悲慘的失敗了,儘管我的哦,所以,巧妙地運用動態的變量名來訪問超全局。

function isset_and_is ($superglobal, $key, $value) 
{ 
    switch (strtoupper($superglobal)) 
    { 
     case 'GET':  $ref =& $_GET;  break; 
     case 'POST': $ref =& $_POST; break; 
     case 'REQUEST': $ref =& $_REQUEST; break; 
     default:  die('megafail'); return; 
    } 

    return isset($ref[$key]) && $ref[$key] == $value; 
} 

if (isset_and_is('post', 'action', 'login')) 
{ 
    // we're probably logging in, so let's process that here 
} 

我的問題:有沒有辦法動態訪問超全局變量,就像我嘗試我的第二個代碼示例中做

所以,我用這個醜陋又卡?如果不是,是否有更好/更有效的方法來完成我在第三個代碼示例中所做的工作?


我的解決辦法:感謝Tom Haigh's answer,這裏是最終的代碼我將要打算:

function isset_and_is ($superglobal, $key, $value) 
{ 
    $ref =& $GLOBALS['_' . strtoupper($superglobal)]; 

    return isset($ref[$key]) && $ref[$key] == $value; 
} 
+1

第一個樣品有什麼問題? – NullUserException 2010-08-24 16:14:32

+0

NullUserException:DRY :) – 2010-08-24 16:17:24

+1

IMO的第一個示例更清晰,DRYer,並且對於任何知道PHP的人都很容易理解。而其他的... – NullUserException 2010-08-24 16:18:38

回答

3

你可以這樣說:

function test($var) { 
    //this 
    var_dump($GLOBALS[$var]); 

    //or this 
    global $$var; //this is needed even for superglobals 
    var_dump($$var); 
} 

test('_GET'); 

所以你可以在你的情況下使用類似這樣的東西

function isset_and_is ($superglobal, $key, $value) { 
    $var = '_' . $superglobal; 
    return isset($GLOBALS[$var]) && ($GLOBALS[$var][$key] == $value); 
} 

$is_login = isset_and_is('GET', 'action', 'login'); 

或者,您也可以參考該變量並使用isset(),例如,

function get_var(& $var) { 
    if (isset($var)) { 
     return $var; 
    } 
    return null; 
} 

//will not give you a notice if not set 
$post_var = get_var($_POST['var']); 

if (get_var($_GET['action']) == 'login') { 
    //stuff 
} 
-1

$_REQUEST默認包含$_GET$_POST內容,爲什麼你需要切換情況。您可以直接使用,消除$superglobal

function isset_and_is ($key, $value) 
{ 
    return isset($_REQUEST[$key]) && ($_REQUEST[$key] == $value); 
} 
+0

例如,如果我只想允許通過「POST」登錄,那麼'$ _REQUEST'是不安全的。 – 2010-08-24 16:19:50

1

如何:http://www.php.net/manual/en/function.filter-input.php

function isset_and_is ($superglobal, $key, $value) { 
    switch($superglobal) { 
    case 'post': 
     $type = INPUT_POST; 
     break; 
    case 'get': 
     $type = INPUT_GET; 
     break; 
    } 
    $var = filter_input($type,$key); 
    if(is_null($var)) return false; 
    return($var == $value); 
} 
+0

你的回答完全忽略了這個問題,並且簡單地爲我的第三個代碼示例提供了一個同樣重要的解決方案。 – 2010-08-24 16:31:57

+1

老實說,我不明白它是如何忽略你的問題。鑑於你實際上可以使用INPUT_ *常量作爲這個函數的參數來擺脫開關,它會成爲一個非常好的解決方案恕我直言。 – Mchl 2010-08-24 16:43:08

2

如果你需要從只有一個源獲取,與湯姆的answer去。但是,如果您對每個變量都這樣做,即如果您始終承認數據可能來自兩個來源,則最好的選擇是合併它們。

你可以使用$_REQUEST,但我建議你反對它。它認爲POST和GET數據的訂單是php.ini可配置的,並且包含其他來源。

做這樣的事情:

$data = array_merge($_GET, $_POST); //POST has precedence 

,然後從$data讓您的數據。

+0

這裏沒有優先順序嗎?我的意思是,如果設置了$ _POST ['var']'和'$ _GET ['var']',它會選擇'$ _GET ['var']' – NullUserException 2010-08-24 16:17:45

+0

我不承認數據總是可以來自兩個來源;相反,數據只會來自其中一個超級全球,取決於我在哪裏訪問它。但是,我希望能夠重新使用此功能。 – 2010-08-24 16:18:45

+0

@Null對不起,你是對的。固定。 – Artefacto 2010-08-24 16:25:30

0

在PHP中,運算符@可以在評估表達式時抑制警告。例如,如果$array[$key]存在,則$array[$key]返回值,如果不存在則返回null,但如果該鍵不存在,則會發出警告。添加@運營商生產@$array[$key]使其相當於array_key_exists($key, $array) ? $array[$key] : null。實際上,isset($something)只是說@$something === null的另一種方式。

那麼試試這個:

if (@$_POST['action'] === 'login') 
{ 
    // we're probably logging in, so let's process that here 
} 

我的PHP項目中使用類似於documentation of ErrorException片斷的東西。這增加了快速失效語義,其中PHP $array[$key]表示拋出ErrorException(如果它不存在),@$array[$key]表示使用null表示找不到(如SQL LEFT JOIN)。

相關問題