Is there any way to dynamically access a superglobal?
Asked Answered
S

5

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;
}
Shawnshawna answered 24/8, 2010 at 16:8 Comment(4)
And what is wrong with the first sample?Illuminance
IMO the first sample is clearer, DRYer and easy for anyone who knows PHP to understand. Whereas the other ones...Illuminance
NullUserException: Valid point, but I'm the only person ever using this code, unless you'd like to use it too.Shawnshawna
Well, if you want to introduce unnecessary complexity and overhead to your code, who am I to deny you? ;-)Illuminance
L
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
}
Leatri answered 24/8, 2010 at 16:12 Comment(0)
P
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.

Presentation answered 24/8, 2010 at 16:15 Comment(2)
Doesn't GET have precedence here? I mean, if $_POST['var'] and $_GET['var'] are set, it will pick $_GET['var']Illuminance
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.Shawnshawna
P
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);
}
Pestilent answered 24/8, 2010 at 16:15 Comment(2)
Your answer completely ignores the question, and simply provides an equally crufty solution to my third code sample.Shawnshawna
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.Pestilent
M
-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);
}
Mom answered 24/8, 2010 at 16:13 Comment(1)
$_REQUEST is unsafe if I only want to allow logins via POST, for example.Shawnshawna
E
-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).

Ediva answered 22/1, 2015 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.