In PHP is wrong to cast $_REQUEST to an object to manage it more easily?
$request = (object) $_REQUEST;
if(isset($request->submit) && isset($request->text) && !empty($request->text))
{
// Do stuff
}
EDIT: i mean any unexpected side effect?
I would say there's nothing wrong with this except obviously the little added time you'll get. What I would do though is run the $_REQUEST array through a cleaner function to validate and clean up the variables. This way you can always know that if your using the object version of the $_REQEUST that it's safe to use.
Update
I would go as far as saying this is probably best practice in the world of modern web applications. I mean look at the MVC frameworks you use (Zend, CodeIgniter, CakePHP etc) they all clean the $_REQUEST, $_GET, $_POST, $_SERVER etc and convert them to objects.
Remeber that the overhead on something like this would be so minimal you wouldn't even notice it. The time PHP takes to parse and output a page is so small, usually smaller than a DOM request for one image.
Nothing I can see that is wrong with that.
It will just allow you to access the associative array as an object.
Not to be argumentative but I don't see how this makes it any easier to manage the $_REQUEST variable. You could write the same line of code like so:
if(isset($_REQUEST['submit']) && isset($_REQUEST['text']) && !empty($_REQUEST['text']))
{
// Do stuff
}
Also, there can be some issues with array keys that don't translate into object property names properly. Take for example $_REQUEST['var name']. Completely legitimate array name but translate the array into an object and you'll be sorely disappointed at the results.
However, if you trust your users that much and want to spend the extra clock cycles creating a new object you could always brute force it.
$request = new stdclass;
foreach($_REQUEST as $field => $value){
$request->$field = $value;
}
Related
2 short questions based on trying to make my code more efficient (I think my ultimate quest is to make my entire (fairly complex) website based on some sort of MVC framework, but not being a professional programmer, I think that's going to be a long and steep learning curve..)
In this code, is there a way to merge the if statement and for loop, to avoid the nesting:
if($fileatt['name']!=null)
{
$attachedFiles = "You uploaded the following file(s)\n";
for($i=0;$i<count($docNames);$i++)
{
$attachedFiles = $attachedFiles. " - " . $docNames[$i] . "\n";
}
}
At the moment, I do the fairly standard thing of splitting my $_POST array from a form submission, 'clean' the contents and store the elements in individual variables:
$name = cleanInput($_POST['name']);
$phone = cleanInput($_POST['phone']);
$message = cleanInput($_POST['message']);
...
(where cleanInput() contains striptags() and mysql_real_escape_string())
I had thought that keeping all the information in an array might my code more efficient, but is there a way to apply a function to all (or selected) elements of an array? For example, in R, this is what the apply() function does.
Alternatively, given that all my variables have the same name as in the $_POST array, is there a way to generate all the variables dynamically in a foreach loop? (I know the standard answer when people ask if they can dynamically generate variables is to use a hashmap or similar, but I was interested to see if there's a technique I've missed)
You can use extract and combine it with array_map
extract(array_map('cleanInput', $_POST), EXTR_SKIP);
echo $name; // outputs name
Be warned that $_POST could be anything and user can then submit anything to your server and it becomes a variable in your code, thus if you have things like
if(empty($varName)) { } // assumes $varName is empty initially
Could easily bypassed by user submitting $_POST['varName'] = 1
To avoid mishaps like this, you can have a whitelist of array and filter out only those you need:
$whitelist = array('name', 'phone', 'message');
$fields = array();
foreach($_POST as $k => $v) {
if(in_array($k, $whitelist)) $fields[$k] = $v;
}
extract(array_map('cleanInput', $fields));
1) To the first question, how to merge the if and the for loop:
Why would you want to merge this, it will only make the code more difficult to read. If your code requires an if and afterwards a for loop, then show this fact, there is nothing bad with that. If you want to make the code more readable, then you can write a function, with a fitting name, e.g. listAttachedFiles().
2) To the question about cleaning the user input:
There is a difference between input validation and escaping. It's a good thing to validate the input, e.g. if you expect a number, then only accept numbers as input. But escaping should not be done until you know the target system. So leave the input as it is and before writing to the db use the mysql_real_escape_string() function, before writing to an HTML page use the function htmlspecialchars().
Combining escape functions before needed, can lead to invalid data. It can become impossible to give it out correctly, on a certain target system.
Personally I think that the performance cost of using an "If" statement is worth the benefit of having easily readable code. Also you have to be sure that you actually use fewer cycles by combining, if there is such a way.
I'm not sure I follow your second question, but have you looked at extract() and array_walk() yet?
Point 1 is premature optimization. And you want get any better performance / readability by doing so. (similar for using arrays for everything).
Point 2 - AaaarrgghhH! You should only change the representation of data at the point where it leaves PHP, using a method approporiate to the destination - not where it arrives in PHP.
To make your for loop more efficient don't use Count() within the condition of your loops.
It's the first thing they teach in school. As the For loops are reevaluating the conditions at each iterations.
$nbOfDocs = count($docNames); //will be much faster
for($i=0;$i<$nbOfDocs;$i++)
{
$attachedFiles = $attachedFiles. " - " . $docNames[$i] . "\n";
}
From my C++ knowledge base, I tend to initialize arrays in PHP by typing:
$foo = array()
Or I may bring this custom from Javascript, anyway, is this of any use?
As there's no problem in doing this:
$foo[45] = 'bar' without initializing it as an array, I guess not.
PS: the tags improvement is really good
Yes it is. At the very least in improves readability of code (so that you don't need to wonder 'where does $foo come from? Is it empty, or is there anything in it?`.
Also it will prevent 'Variable '$a' is not set notices, or Invalid argument passed to foreach in case you don't actually assign any values to array elements.
Either method is perfectly acceptable. As mentioned, this practice of using the array() construct is typically carried over from another language where you initialize before populating. With PHP, you can initialize an empty array and then populate later, or you can simply establish an array by assignments, such as $variableName[0] = "x";.
#petruz, that's the best way to do this, no only it will save you from nasty PHP error messages saying that function expects the parameter to be an array but, IMHO, this is the best way to write code. I initialise a variable before using it
Initializing variables before use is good practice. Even if it is not required.
I've had problems (in older versions of PHP, haven't tried recently) where I was acting on array with array_push or something and PHP barked at me. As a general rule it's not necessary, but it can be safer, especially if you're dealing with legacy code; perhaps you're expecting $foo to be an array, but it's actually a boolean? Bad things ensue.
It's good practice. Sooner or later you'll encounter a situation where you might want to do something like this:
array_push($foo, '45');
Which will throw a notice, whereas:
$foo = array();
array_push($foo, '45');
won't.
With initialization:
$myArray = array();
if ($myBoolean) {
$myArray['foo'] = 'bar';
}
return $myArray;
Without initialization:
if ($myBoolean) {
$myArray['foo'] = 'bar';
}
return $myArray;
In the first case it's clear what you want to happen if $myBoolean is false. In the second case it is not and php may throw a warning when you try and use $myArray later. Obviously this is a simplified case, but in a complex case the "if" may be a few lines down and/or not even exist until someone comes along and adds it later without realizing the array wasn't initialized.
While not necessary, I have seen lack of initialization cause non-obvious logic problems like this in complex functions that have been modified a lot over time.
I'm trying to migrate a website from one host to another. On the first host, when you submit a form, all of the form values are automatically stuck into variables with the input name (this is PHP). On the new host, these values are all null unless I do this:
$data = $_GET['data'];
Is there a PHP configuration setting that is causing this? If there isn't, is there an easy way to loop through all of the $_GET variables and automatically assign their values to a variable with the same name?
Thanks!
The setting is register_globals, but it is now deprecated and strongly advised against using it because it is a security risk. Anyone can set variables in your script which might interact in a negative or unexpected way with your code.
If you absolutely must, you can do it like this:
foreach ($_GET as $key=>$value) {
$$key = $value;
}
or, more simply:
import_request_variables("g");
or, to make it a little safer:
import_request_variables("g", "myprefix_"); // This way forces you to use "myprefix_"
// in front of the variables, better ensuring you are not unaware
// of the fact that this can come from a user
extract($_GET) could also work, as someone else pointed out, and it also allows specification (via extra arguments) of adding a prefix or what to do if your extraction conflicts with an already existing variable (e.g., if you extracted after you defined some other variables).
Look at the extract function : http://www.php.net/manual/en/function.extract.php
You could do something like this:
foreach ($_GET["data"] as $name => $value){
$$name = $value;
}
The issue with this is that it makes it easy for people to fiddle with the variables in your script. I could visit http://yoursite.com/?sql=DELETE+FROM...
I'd advise against doing this and just sticking to using $_GET.
Your question infers you are not doing any filtering or validation when assigning $_GET['data'] to $data, unless you are doing these kind of checks further down your script.
From what I have seen most programmers would do this first, in an effort to fail early if expected data did not match expectations, so that the above assignment in the case of expecting a positive int would become something like:
if( isset($_GET['data']) && (int)$_GET['data'] === 0){
//fail
}else{
$data = $_GET['data'];
}
So seeing just plain
$data = $_GET['data']
makes me wince.
Solution?
Apparently there isn't a faster way, I'm okay with that.
I am just learning php and I am trying to figure out some good tips and tricks so I don't get into a bad habit and waste time.
I am passing in values into a php script. I am using $_GET so the URL looks like this:
/poll_results.php?Sports=tennis&cat=Sports&question=Pick+your+favorite+sports
Now I know how to accept those values and place them into variables like so:
$sports = $_GET['Sports'];
$cat = $_GET['cat'];
$question = $_GET['question'];
Super simple yet if I am passing 5 - 6 things it can get bothersome and I don't like typing things out for every single variable, that's the only reason. I know there is a better way of doing this. I have tried list($var, $var, $var) = $_GET but that doesn't work with an associative array just indexed ones (i think).
I also tried variable variables like so:
foreach($_GET as $value) {
$$values = $value;
echo $$values;
}
But that gave me a Notice: Undefined variable: values in poll_results.php on line 14. Line 14 is the $$values = $value. I don't know if that's a big deal or not... but I'm not turning off error reporting as I am still in the process of building the script. It does do what I want it to do though...
Any answers will be copied and pasted into my question so the next person knows :D
Thanks guys!
Your second bit of code is wrong. It ought to be like
foreach ($_GET as $key => $value) {
$$key = $value;
}
if i understand your intent. However, you're basically reinventing register_globals, which....eh. That'll get ya hacked.
If you have certain variables you want to get, you could do like
foreach (array('Sports', 'cat', 'question') as $key)
{
$$key = $_GET[$key];
}
which is less likely to overwrite some important variable (whether by accident or because someone was messing around with URLs).
Use parse_url() to extract the query string from a URL you've got in a string, then parse_str() to extract the individual arguments of the query string.
If you want to pollute your script with the contents of the superglobals, then you can use extract(). however, be aware that this is basically replicating the hideous monstrosity known as "register_globals", and opens all kinds of security vulnerabilities.
For instant, what if one of the original query arguments was _GET=haha. You've now trashed the $_GET superglobal by overwriting it via extract().
I am just learning php and I am trying to figure out some good tips and tricks so I don't get into a bad habit and waste time.
If I am passing 5 - 6 things it can get bothersome and I don't like typing things out for every single variable, that's the only reason.
What you are trying to do will, unless curbed, become a bad habit and even before then is a waste of time.
Type out the variables: your digits like exercise and your brain can take it easy when it doesn't have to figure out which variables are available (or not, or maybe; which would be the case when you use variable variables).
You can use
foreach($_GET as $key => $value)
To preserve the key and value associativity.
Variable variables (the $$value) are a bad idea. With your loop above say you had a variable named $password that is already defined from some other source. Now I can send $_GET['password'] and overwrite your variable! All sorts of nastiness can result from this. It's the same reason why PHP abandoned register_globals which essentially does the same thing.
My advice: use $_POST when possible. It keeps your URLs much cleaner for one thing. Secondly there's no real reason to assign the array to variables anyway, just use them where you need them in the program.
One good reason for this, especially in a large program, is that you'll instantly know where they came from, and that their data should not be trusted.
Ok I cannot remember the details on this but on some servers you can use
$var instead of $_GET['var'] to access a variable in the URL, I know this is BAD but I can't remember why it is bad?
I think you mean Register Globals.
You shouldn’t use them because you cannot distinguish the source of that variable values since they can come from any source of the EGPCS variables (Environment, GET, POST, Cookie, Server).
So if you have a the $var, you cannot say if the value is either from $_ENV['var'], $_GET['var'], $_POST['var'], $_COOKIE['var'] or $_SERVER['var'].
The feature is called Register Globals and it allows people to inject variables into your code. See the documentation for examples; here's one:
<?php
// define $authorized = true only if user is authenticated
if (authenticated_user()) {
$authorized = true;
}
// Because we didn't first initialize $authorized as false, this might be
// defined through register_globals, like from GET auth.php?authorized=1
// So, anyone can be seen as authenticated!
if ($authorized) {
include "/highly/sensitive/data.php";
}
?>
You can use that if your server has register_globals set to 1 (or true) on the php.ini file.
At some point, this started to be off by default, and applications started to break, which is a reason why this is a bad practice.
You can see a list of php.ini variables here.
It's also bad because you can confuse yourself with the way that PHP will scope your variables. You may wind up overwriting data if you aren't careful. Also, using $_GET is much clearer as to what you are attempting to accomplish.
Because letting people inject values into arbitrary variables is a very bad thing. You could be storing anything there and they could overwrite some value that compromises your security. Remember to use isset to check that a value has been set before trying to use it.
It's bad because if you're not careful to initialize every variable before you use it (something that PHP won't force you to do), people can easily cause your code to do Very Bad Things with a request as simple as /myapp/index.php?admin_privileges=1.
The setting is called REGISTER_GLOBALS and it was discussed here:
Why is REGISTER_GLOBALS so bad?
If you can do that, then "register_globals" is turned on. This is bad because you won't know where a variable came from, and it mixes your variables with the ones any user can inject via the URL. Read more here: http://www.php.net/manual/en/security.globals.php
Once you get used to using $_POST, $_GET, etc your code's purpose will be easier to read and much, much easier to maintain.
Register globals would work but it's going to go away in a future version of PHP. Not to mention that it really is wrong to have it enabled.
You can use extract() for a more controlled behavior. It will extract the keys from an array (in this case, $_GET) into the local context as variables. You can give them a common prefix so that they don't collide with your existing variables. And you can filter the array beforehand to make sure you're only getting the expected variables.
int extract( $var_array [, $type = EXTR_OVERWRITE [, $prefix ]] )
Import variables from an array into the current symbol table.