Question

As a web developer, I'm always using this approach to something like a login form or other “save” operation (ignoring the dangers of directly accessing input variables):

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

To make this less tedious and keeping in line with DRY principles (sort of), I cooked this up:

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
}

This fails miserably, despite my oh-so-clever use of dynamic variable names to access the superglobal.

So, I'm stuck using this ugly:

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
}

My question: Is there a way to dynamically access the superglobal variables like I'm attempting to do in my second code sample? If no, is there a better/more efficient way to accomplish what I'm doing in the third code sample?


My solution: Thanks to Tom Haigh's answer, here's the final code I'll be going with:

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

    return isset($ref[$key]) && $ref[$key] == $value;
}
Was it helpful?

Solution

You can do it like this:

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

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

test('_GET');

so you could use something like this in your case

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');

Or alternatively you can take the variable by reference and use isset(), e.g.

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
}

OTHER TIPS

If you need to fetch from only one source, go with Tom's answer.

However, if you're doing this for every variable, i.e., if you always admit that data can come from two sources, the best alternative is to merge them.

You could use $_REQUEST, but I'd advise you against it. The order it considers POST and GET data is php.ini configurable, and it includes other sources.

Do something like:

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

and then get your data from $data.

How about: 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);
}

In PHP, operator @ suppresses warnings while evaluating an expression. For example, $array[$key] returns the value with that key if it exists or null if not, but it raises a warning if the key does not exist. Adding the @ operator to produce @$array[$key] makes it equivalent to array_key_exists($key, $array) ? $array[$key] : null. In fact, isset($something) is only another way of saying @$something === null.

So try this:

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

My PHP projects use something similar to the snippet in the documentation of ErrorException. This adds fail-fast semantics, where PHP $array[$key] means throw an ErrorException if it's not there and @$array[$key] means use null to mean not found (like an SQL LEFT JOIN).

When $_REQUEST by default contains the contents of $_GET and $_POST, why do you need switch-case. You can directly use this and eliminate $superglobal:

function isset_and_is ($key, $value)
{
    return isset($_REQUEST[$key]) && ($_REQUEST[$key] == $value);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top