7

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;
}
Community
  • 1
  • 1
Abraham Vegh
  • 1,490
  • 1
  • 12
  • 32

5 Answers5

3

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
}
Tom Haigh
  • 57,217
  • 21
  • 114
  • 142
2

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.

Community
  • 1
  • 1
Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • Doesn't GET have precedence here? I mean, if `$_POST['var']` and `$_GET['var']` are set, it will pick `$_GET['var']` – NullUserException Aug 24 '10 at 16:17
  • I'm not admitting data can always come from two sources; on the contrary, data will only ever come from one of the superglobals, depending on where I'm accessing it. But, I want to be able to re-use this function. – Abraham Vegh Aug 24 '10 at 16:18
1

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);
}
Mchl
  • 61,444
  • 9
  • 118
  • 120
  • Your answer completely ignores the question, and simply provides an equally crufty solution to my third code sample. – Abraham Vegh Aug 24 '10 at 16:31
  • 1
    Honestly, I can't see how it's ignoring your question. Given you can actually use INPUT_* constants as an argument to this function to get rid of the switch, it cen become a really nice solution IMHO. – Mchl Aug 24 '10 at 16:43
-1

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).

Damian Yerrick
  • 4,602
  • 2
  • 26
  • 64
-1

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);
}
shamittomar
  • 46,210
  • 12
  • 74
  • 78