有没有办法动态访问超全球?

时间:2010-08-24 16:08:49

标签: php superglobals

作为一名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;
}

5 个答案:

答案 0 :(得分: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 :(得分:2)

如果您只需要从一个来源获取,请使用Tom的answer

但是,如果您为每个变量执行此操作,即,如果您始终承认数据可以来自两个来源,则最好的选择是合并它们。

你可以使用$_REQUEST,但我建议你不要这样做。它认为POST和GET数据的顺序是php.ini可配置的,它包含其他来源。

做类似的事情:

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

然后从$data获取您的数据。

答案 2 :(得分: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);
}

答案 3 :(得分:0)

在PHP中,运算符@在计算表达式时会抑制警告。例如,$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表示使用LEFT JOIN表示未找到(如{ SQL {{1}})。

答案 4 :(得分:-1)

默认情况下$_REQUEST包含$_GET$_POST的内容时,为什么需要切换大小写。您可以直接使用它并删除$superglobal

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