2010-08-24 36 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)。

相关问题