PHP $_GET/$_POST via variable variables - php

I'm attempting to dynamically access both the $_GET and $_POST arrays, among others, using variable variables. The reason I'm trying to do this is so that I can perform similar actions on multiple arrays without needing to declare specific iterations for each. I'm reasonably sure this is possible, as PHP's documentation says it is able to use variable variables to dynamically access an array, however I'm unable to get it to work. A simple demonstration is when I'm attempting to verify that a certain property has been set.
if(isset(${$this->_array}[$property])) { return ${$this->_array}[$property]; }
else { return null; }
When I run the above script I always get null, however when I statically seek the desired property, manually using $_GET or $_POST, I get the desired outcome. I have triple checked $this->_array and $property and they are returning the correct string values. Are these arrays unavailable for such access, or am I doing something wrong?

Superglobals (such as $_POST) can not be used as variable variables within functions.
You could say something like $post = $_POST; and then use 'post' and it'd work, but directly using '_POST' won't.

Superglobals cannot be referenced as variable variables inside of classes or methods, so this will work:
<?php
$var = "_GET";
print_r(${$var});
But this will not:
<?php
test();
function test() {
$var = "_GET";
print_r(${$var});
}
I suspect that there is a better way to do what you are trying to accomplish.
http://php.net/manual/en/language.variables.superglobals.php#refsect1-language.variables.superglobals-notes

Whatever you're doing wrong, using variable variables is probably making it worse. For your own sanity, please stop. They should never be deployed in production code under any circumstances. They're impossible to debug, and using them in your code is like trying to read something that someone else wrote with their feet. If they have particularly dexterous feet, then perhaps you can understand what they're doing. But 99.9999% of the time, it is better to just use normal arrays.
That being said, try $_REQUEST instead.

There's already an array that contains both $_GET and $_POST. It's named $_REQUEST. Having said that, it can also contain the contents of $_COOKIE depending on the request_order setting, but the default is just $_GET and $_POST.

You say you want to access both the $_GET and $_POST arrays, among others -- what are these 'others'? You can use $_REQUEST to check the contents of $_GET, $_POST, and $_COOKIE all at once.

you can do this but dont know if it is a good coding practice
if( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
$method = '_POST';
}
else {
$method = '_GET';
}
$data = $$method;

You can create an associative array that references both arrays, and use that.
$params = [
'_GET' => $_GET,
'_POST' => $_POST
];
Then you can use
return $params[$this->_array][$property] ?? null;

Related

Undefined variable _POST if called dynamically [duplicate]

I'm attempting to dynamically access both the $_GET and $_POST arrays, among others, using variable variables. The reason I'm trying to do this is so that I can perform similar actions on multiple arrays without needing to declare specific iterations for each. I'm reasonably sure this is possible, as PHP's documentation says it is able to use variable variables to dynamically access an array, however I'm unable to get it to work. A simple demonstration is when I'm attempting to verify that a certain property has been set.
if(isset(${$this->_array}[$property])) { return ${$this->_array}[$property]; }
else { return null; }
When I run the above script I always get null, however when I statically seek the desired property, manually using $_GET or $_POST, I get the desired outcome. I have triple checked $this->_array and $property and they are returning the correct string values. Are these arrays unavailable for such access, or am I doing something wrong?
Superglobals (such as $_POST) can not be used as variable variables within functions.
You could say something like $post = $_POST; and then use 'post' and it'd work, but directly using '_POST' won't.
Superglobals cannot be referenced as variable variables inside of classes or methods, so this will work:
<?php
$var = "_GET";
print_r(${$var});
But this will not:
<?php
test();
function test() {
$var = "_GET";
print_r(${$var});
}
I suspect that there is a better way to do what you are trying to accomplish.
http://php.net/manual/en/language.variables.superglobals.php#refsect1-language.variables.superglobals-notes
Whatever you're doing wrong, using variable variables is probably making it worse. For your own sanity, please stop. They should never be deployed in production code under any circumstances. They're impossible to debug, and using them in your code is like trying to read something that someone else wrote with their feet. If they have particularly dexterous feet, then perhaps you can understand what they're doing. But 99.9999% of the time, it is better to just use normal arrays.
That being said, try $_REQUEST instead.
There's already an array that contains both $_GET and $_POST. It's named $_REQUEST. Having said that, it can also contain the contents of $_COOKIE depending on the request_order setting, but the default is just $_GET and $_POST.
You say you want to access both the $_GET and $_POST arrays, among others -- what are these 'others'? You can use $_REQUEST to check the contents of $_GET, $_POST, and $_COOKIE all at once.
you can do this but dont know if it is a good coding practice
if( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
$method = '_POST';
}
else {
$method = '_GET';
}
$data = $$method;
You can create an associative array that references both arrays, and use that.
$params = [
'_GET' => $_GET,
'_POST' => $_POST
];
Then you can use
return $params[$this->_array][$property] ?? null;

Passing $_POST/$_GET as a parameter to function

I came across an interesting piece of PHP code which has me a bit stumped as to why the author has chosen to do this.
function do_something($db, $post_vars){
foreach($post_vars as $key => $value{
$vars[$key] = mysqli_real_escape_string($db, $value);
}
return $vars;
}
$db = mysqli_connect("myhost","myuser","mypassw","mybd") or die("Error " . mysqli_error($link));
do_something($db, $_POST);
It got me thinking about why someone would want to pass $_POST as a variable and just not access it directly inside the function? The only benefit I could think of (and this was a bit of a long shot) was if we were to append other information to $_POST before calling the function (such as):
function do_something($db, $post_vars){
foreach($post_vars as $key => $value{
$vars[$key] = mysqli_real_escape_string($db, $value);
}
return $vars;
}
$db = mysqli_connect("myhost","myuser","mypassw","mybd") or die("Error " . mysqli_error($link));
foreach($_POST as $post_key => $post_value){
$post[$post_key] = $post_value;
}
$post['my_custom_var'] = "a";
do_something($db, $post);
There is, however, no evidence of this practise anywhere in the code. Just calls to do_something() with $_POST being passed as an arugment.
My question then is, is there any benefit in doing it like this that I've missed or did the author simply not understand that $_POST is a global variable?
A complete long shot: Is there perhaps even any well intended "later additions" they could make to this (such as my example) that would almost justify this practise or is this just a case of misunderstanding. Or perhaps is there a security implication that could justify the practise?
IMHO it's a practice of abstraction, and there are benefits:
Generality: by receiving $_POST as a parameter, the function becomes less tightly coupled to $_POST. The function may serve more scenarios & possibly be more reusable.
Inversion of control: because the function's dependency($_POST) is injected from outside, you have more control over the function. It is a bit unlikely but let's suppose your form has been updated and now you need to submit via GET method. Without modifying the function's body, passing in $_GET on the caller's side, is enough to reflect the change.
Test fixture isolation: To mock FORM inputs to test a certain code path in the function, it is better access global states (such as $_POST) in an abstracted way, so that the test itself does not bring side effects to other part of the system.
In general, there is a very good reason to pass $_POST or $_GET or whatever array you want as argument instead of accessing it through the auto-global variables. It's called "dependency injection" and it's a key feature for testable code.
Another reason to not use auto-globals (or global variables, in general) is the readability of the code.
Compare:
function do_something($db, array $post_vars) {
// many lines of code here, you don't want to read them
}
do_something($db, $_POST);
with
function do_something_else($db) {
// many lines of code here that use $_POST, you don't want to read them either
}
do_something_else($db);
In the first case its clear that function do_something() operates over the values of $_POST (or $_GET or whatever other array full of data you pass it as argument). You don't have to read the function's code to know that; all the relevant information is displayed in the function header and in the example usage.
In the second case, the behaviour of function do_something_else() depends on the content of $_POST but one cannot know this without looking at its code.
Back to the code you posted, it doesn't look like it was written having testability in mind.
Take a look only at:
foreach($_POST as $post_key => $post_value){
$post[$post_key] = $post_value;
}
It basically does $post = $_POST in more words.
It's a good idea to sanitize the $_POST Superglobal before passing it as an argument of a function, then escape it inside the function that has your query logic.
What he does is escaping every POST variable through mysqli_real_escape_string function, which makes sure you avoid SQL Injection attacks.Then he returns the array (with escaped values) by calling : return $vars;
He might have used a function to do this because he intends to repeat the steps several times throughout the application and he might just call that function and passing the variables instead of writing the code over and over again.
MAKE SURE YOU ALWAYS ESCAPE USER INPUT BEFORE MAKING ANY DATABASE CALLS.

Does Yii::$app>request->post() clean $_POST variables?

Just want to know if Yii2 cleans the $_POST variables if I use this method:
Yii::$app->request->post()
If suppose I am using the following method to get the value of x:
$x = Yii::$app->request->post('x');
Does Yii2 framework internally cleans the $_POST variable? Or else we have to do it manually?
No, the $_POST stays untouched, in its initial condition.
Yii just copies and holds it in private $_bodyParams property.
And I don't think it's a good practice to manually modify or clean $_POST parameters.

Besides returning the data, is there a way to pass up variables to a different scope in PHP?

Here's a pretty obscure one; and I know that I'm reaching here - but I'm trying to find an 'elegant' solution to adding a number of variables to [effectively] the parent scope.
Here's the example:
File 1:
<?
ImportPost();
// Do something with imported variables.
?>
File 2:
<?
function ImportPOST()
{
foreach( $_POST as $Key => $Value )
VariableToParentScope($Key, $Value);
}
?>
So that I would end up with the 'simple' variable names in my first ('DoSomething') method. One thing I find myself doing over and over again is building this small foreach to perform this exact task - but I don't see many other ways to achieve it, other than placing it all in a class - which is generally preferable anyway, but let's say this is in the context of a file that is just some non-OOP PHP.
I've also considered reading the contents of 'File 1', inserting the variables before the rest of the files contents, and then running it - and while this may be the closest thing to a 'proper' implementation there is, I'm still trying to figure out if there is a simpler, or more appropriate one.
Any thoughts?
I.E. - Edit the stack? 0_o
You can use extract to build some variables from an array - here's an example:
function importVars()
{
return array('foo'=>'xyzzy', 'bar'=>'123');
}
function demo()
{
extract(importVars());
echo "foo is $foo\n";
echo "bar is $bar\n";
}
demo();
I'd be wary of doing this with external data such as from $_POST - better to carefully validate what you're bringing in.
You could use $GLOBALS, which essentially would make your variables available in the global scope:
//assuming $_POST = ['foo'=>'bar']
echo $foo; // Notice: Undefined variable
function ImportPOST()
{
foreach( $_POST as $Key => $Value )
$GLOBALS[$key] = $Value;
}
ImportPOST();
echo $foo; // "bar".
However, as you said yourself, it's bad practice to interfere the global scope in that manner.
This seems like a potential security risk to me. I would push all the vars to an array, then pass that around. Or at most, add this array to the global scope. That way, you keep all post data contained in one place, rather than at the same level as all other global variables.

How can i create a function that takes un-assigned variable in PHP

I'm trying to make a function that takes a variable whether it was set or not,
like the function isset()
//we have this array
$array = array();
isset($array["test"]);//this one is valid
myFunc($array["test"]);//this one is not valid
how can i let my function take not set variables?
Pass the argument as a reference
http://php.net/manual/en/language.references.pass.php
function myFunc(&$val)
{
return isset($val);
}
var_dump(myFunc($undefined));
It's common to come across this problem if you're using $_GET and friends, because you can't rely on a given field being passed into your program.
I use a utility class for this, so I can avoid errors with unset vars and also populate defaults into them.
<?php
function defArrayElem(&$array, $key, $default=null) {
if(!isset($array[$key])) {$array[$key]=$default;}
}
//repeat for all the $_GET/$_POST vars you expect...
defArrayElem($_GET,'keyname','default-value');
?>
Now you don't need to worry about checking if they're set or not.

Categories