10

I really hate global variables - maybe its the C# programmer in me but when I'm working in PHP I grit my teeth every time I have to do something like this:

$strUsername = $_GET['username'];

Yes, I'm grossly oversimplifying it and yes yes I sanitize all of this properly. In fact, for the framework that I built, all of the superglobals are grabbed almost at the beginning of execution and are dependency-injected from there on out.

I ran across this function in the PHP manual (you truly learn something new every day): filter_input_array().

So now, technically, I can do this instead of grabbing everything from the GET superglobal:

$GETdata = filter_input_array(INPUT_GET);

.... and so on and so forth with the others like POST, REQUEST, etc. My question is: should I use filter_input_array and so avoid the scourge of superglobals, or is there some reason to stick with them and forget about using the filter_input functions? What is everyone else's experience with this?

EDIT: I forgot one thing - the filter_input functions are blind to any script-level modifications you make to the superglobals so if I do: $_GET['cheese'] = 'puff'; trying to do filter_input(INPUT_GET, 'cheese'); later will return null. This is fine since I dependency inject everything but it could catch somebody off guard later, if they are unaware.

Jarrod Nettles
  • 6,193
  • 6
  • 28
  • 46
  • From a performance standpoint, do you really want to filter the input every time you need them? e.g. You call `foo()` and sanitize them there, but what if `bar()` needs them as well? Do you re-sanitize? – Brad Christie Apr 14 '11 at 15:42
  • If you **don't need** any filtering - why to bother with 1 pointless function call? – zerkms Apr 14 '11 at 15:42
  • 1
    Superglobals exist for a reason. You might be wondering what they're good for, but until you run into a problem where they're actually incredibly useful - you'll probably frown upon them and try to avoid them by creating wrappers that create yet another array. – Michael J.V. Apr 14 '11 at 15:43
  • 1
    isn't "scourge of superglobals" a little dramatic? :] – Ryan Apr 14 '11 at 15:44
  • @BradChristie & @zerkms - My question isn't really about filtering or sanitization or validation or anything. Its about that first, initial grab of GET and POST data that are foreverafter dependency injected. Models handle their own validation and filtering, and views handle sanitizing output. – Jarrod Nettles Apr 14 '11 at 15:50
  • @Jarrod: wrap your $_GET and $_POST with some `Request` class and become happy then ;-) – zerkms Apr 14 '11 at 15:52
  • possible duplicate of [Is using superglobals directly good or bad in PHP?](http://stackoverflow.com/questions/3498207/is-using-superglobals-directly-good-or-bad-in-php) –  Apr 13 '14 at 14:08

7 Answers7

9

Using filter_input_array is still using superglobals because it's still getting its data from one of the superglobal arrays.

There's nothing wrong with getting your data from one of these arrays, its really the only way to get the data actually. You just have to make sure you escape it for whatever you're using it in.

htmlentities for html, prepared string for pdo, mysql_real_escape_String for mysql_ functions etc...

Galen
  • 29,976
  • 9
  • 71
  • 89
  • Not true. `filter_input_array(INPUT_SERVER)` will not return `REQUEST_TIME` or `REQUEST_TIME_FLOAT`. Thus, `filter_input_array()` is getting values without using the superglobals. The real question is if you are creating a `Request` object, should you seed it with `$_SERVER` or `filter_input_array()`. Ultimately, wrapping the values derived from superglobals and functions is easier, but there is another way: `php://input` – Anthony Rutledge Jul 27 '18 at 16:47
5

Why are global variables bad?

The common argument is, because you introduce unnesseccary dependencies to an external state.

Your solution does not prevent that, it only hides it.

A better solution would be, imho, to provide $_GET as an argument, as in

function myController($get) {
   $user = Model::get_user($get['userid']);
   render_view('user.html', $user);
}

myController($_GET)

as that adresses the reason why global variables are considered bad.

Galen
  • 29,976
  • 9
  • 71
  • 89
keppla
  • 1,753
  • 2
  • 15
  • 29
  • 2
    Yep, and this is called `dependency injection`. To improve your code a little it could be nice to rename `$get` to something like `$request`. – zerkms Apr 14 '11 at 15:48
  • 2
    i just wrote it down, i dont even remember PHPs naming conventions since i left it for sweet python :). maybe also an interesting term to search: law of demeter. – keppla Apr 14 '11 at 15:50
  • I mentioned in the original question that everything is dependency injected. Nothing steams me more than running across a floater $_GET in the middle of a class method. And yes, I realize that I am simply hiding the problem. – Jarrod Nettles Apr 14 '11 at 15:54
  • @jarrod - so then, why would you try to replace $_GET with an equivalent statement instead of moving said code to your superiour style used in your framework? – keppla Apr 14 '11 at 15:57
3

I use PHP superglobals, but only at the library level in my Framework. This is framework all controllers have access to the request object, which in turn access the superglobals. This allows you to write tests for your controller by making a mock request object populated with your test parameters. It's all about good OO design and good design patterns.

Accessing the superglobals directly everywhere without any abstraction in place is an anti-pattern.

Easen
  • 296
  • 1
  • 5
1

I really hate those global variables as well. I would definitely use filter_input_array and use the array whenever needed. This solves a lot of global-related bugs and prevents you from spending hours debugging these hard-to-find globals.

I think that filter_input_array is the wtg!

Lucas d. Prim
  • 787
  • 1
  • 5
  • 17
  • 4
    besides hatred, whats the point? in what way is a statmement that is equivalent to a global variable better than the global variable – keppla Apr 14 '11 at 15:46
  • in this case you wouln't pollute your main scope with cluttered global variables, replacing it for only one global, which minimizes code complexity. Anyway, i like your approach. – Lucas d. Prim Apr 14 '11 at 16:12
  • Be careful about `$_SERVER` and `filter_input_array(INPUT_SERVER)`.They do not return the same output. – Anthony Rutledge Jul 27 '18 at 16:53
1

I don't think someone knows perfect answer :)

Sometime I use it, sometimes I get data just like $_GET['data'], sometimes I even use import_request_variables().

On some project I have special Class, that process POST, GET, REQUEST and do something like this: POST::getValue('username') or GET::getValue('session_id') or COOKIE::getValue('last_time_seen')...

Brad
  • 159,648
  • 54
  • 349
  • 530
Nemoden
  • 8,816
  • 6
  • 41
  • 65
  • Unfortunately `import_request_variables()` is now deprecated, although you can still use `extract($_GET)` to do the same thing. – nullability Jan 30 '14 at 20:25
  • not exactly, `import_request_variables` operated on `$_POST`, `$_GET` and `$_COOKIE` arrays. – Nemoden Jan 31 '14 at 02:15
  • You're right, `extract($_REQUEST)` would work though. – nullability Jan 31 '14 at 16:36
  • Not really. What if you have `$_GET['city'] = 1;`, `$_POST['city'] = 2;` and `$_COOKIE['city] = 3;` ? ;) – Nemoden Feb 03 '14 at 06:17
  • Then the latter would override the others, just as `import_request_variables` would have done. The only difference is that you can choose the order in which they are imported using the `$types` argument. – nullability Feb 03 '14 at 16:38
  • Using extract() on a super global can be a bad idea from a security point of view. If you must use it, use a prefix and/or the EXTR_SKIP flag, and don't do your extraction in the global scope. – christophe Oct 09 '14 at 14:06
1

If you really don't like superglobals, why not to write your own implementation for cleaning like vB_Input_Cleaner class here?

http://members.vbulletin.com/api/

Vladislav Rastrusny
  • 29,378
  • 23
  • 95
  • 156
0

Some years ago it was even worse, the parameter &x= in the URL appeared as global $x. Amyway, if you don't use $_GET, except in the framework, it does not exists.

ern0
  • 3,074
  • 25
  • 40