I have the same question but...I'm redirecting the user depending on an if statement using headers to a dynamic page that is constructed through a function. For that function to work properly, it needs the parameters passed in the GET portion of the headers.
According to what to the answers provided, this is a bad practice. What way should I be doing it?
function page($title,$msg){
$title = $_GET['title'];
$msg = $_GET['msg'];
echo '<h1>'.$title.'</h1>';
echo '<p>';
switch($msg){
case 1:
echo 'dwasdwadawdwadwa';
break;
case 2:
echo 'wasdadwadwdad';
break;
default:
echo 'wadasdasd';
break;
}
echo '</p>';
}
ps: feel free to point out anything else you see wrong.
I found this but it doesn't really help me.
Although you aren't necessarily using the $_GET input for something that requires security considerations (in this case), it's a bad practice not to be sanitizing values from the URL.
Not only should you be checking for malicious input (especially if you are using the input to query a database), but you should be validating that expected integer values are indeed integers, and required strings are not empty.
Also, your page($title, $msg) function accepts $title and $msg and sets them, even though they are not passed by reference.
If you expect to modify the input parameters, pass them by reference.
If you need to use the input parameters, don't overwrite them immediately.
If you don't need input parameters and only use values from $_GET locally to your function, declare page() without any arguments.
The answer to the question you linked suggests that functions should not rely on any external (e.g. global) variables. $_GET and $_POST (amongst others) are 'super globals', a language feature of PHP that makes them available in any scope. This means they may be unexpectedly modified from anywhere in your scripts.
One way to help avoid this is to avoid using super globals in methods and instead - as the answer to the other question suggests - is to instead require parameters for the variables you would otherwise get from the super globals.
E.g., instead of:
function add_user() {
$user = $_GET['user'];
// ...
}
add_user();
You would use:
function add_user($user) {
// ...
}
add_user($_GET['user']);
In your situation, what you would want is:
function page($title, $msg){
echo '<h1>'.$title.'</h1>';
echo '<p>';
switch($msg){
case 1:
echo 'dwasdwadawdwadwa';
break;
case 2:
echo 'wasdadwadwdad';
break;
default:
echo 'wadasdasd';
break;
}
echo '</p>';
}
Then, when you call page you would call it as:
page($_GET['title'], $_GET['msg']);
Why do you need to use GET? you can access all the same properties if you use POST which is also more safe
Not sure if i understand your question, but here is some code i use handle my ajax calls with:
$mc = new MyClass();
echo $mc->{$_GET["operation"]}($_GET);
This means "operation" refers to your method name inside MyClass and i dont have to add a new switch statement for each method. Now i can just add a function "addRecord($args)" to MyClass, and my ajax call would look like this:
ajax_users.php?operation=addRecord&name=testuser&dob=1980-01-01
your php function receives the arguments in an array, so inside function addRecord() you have to access the variables like $args['name'] and $args['dob'], and it dosnt matter how many parameters you have to pass on to your method.
Make sure you use prepared statements here or proper escaping to prevent sql injections.
Related
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.
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.
I'm creating a website and somewhere in the code I need to query for a user attribute (ex:account state) and in the same row I have the reason, case is account state is "suspended".
I'm trying to minimize the requests to the database, so I created a function to verify account state.
function getAccountState($userid,$reason){}
What I am trying to do is if account state is "suspended" I would change the $reason to "the database reason".
I've already done that but if I change the $reason inside the function, outside the function it will not change.
I searched for "php pointers" on google but I think there is not such thing.
Is there a way to do this? Other way I'll just make another database request...
You could of course pass the variable by reference but as you don't seem to need it, I would just return it from the function:
function getAccountState($userid){
// your code
return $reason;
}
and call it like:
$reason = getAccountState($userid);
If you want to stay your code as it is now, you could pass the variable by reference:
function getAccountState($userid,&$reason){}
^ like so
You could consider passing it in by reference. Or perhaps just changing the function to return the correct information.
In the definition of functions you can tell that $reason argument is passed by reference, not value. To do so, use & in front of variable:
function getAccountState($userid,& $reason){}
You are looking for references, in PHP terminology, not pointers.
They work this way :
function getAccountState($userid, &$reason){ // Notice the &
$reason = "database locked"; // Use it as a regular variable
}
getAccountState(12345, $reason); // Here, it is written as a regular variable, but it is a ref.
echo $reason; // echoes "database locked"
add_filter('wp_list_pages_excludes', 'gr_wp_list_pages_excludes');
function gr_wp_list_pages_excludes($exclude_array) {
$id_array=$array('22');
$exclude_array=array_merge($id_array, $exclude_array);
return $exclude_array;
}
I'm a newbie to wordpress. The above code works fine. But I need to pass additional argument, say $mu_cust_arg to the function gr_wp_list_pages_excludes. How can I make use of it via apply_filters, or any other methods?
Any help is appreciated.
Thanks in advance.
You can indeed add multiple arguments to a filter/action, you just need to tell WordPress how many arguments to expect
Example, which won't work:
add_filter('some_filter', function($argument_one, $argument_two) {
// won't work
});
apply_filters('some_filter', 'foo', 'bar'); // won't work
It will fail with an error that too many arguments was provided.
Instead, you need to add this:
add_filter('some_filter', function($argument_one, $argument_two) {
// works!
$arugment_one; // foo
$arugment_two; // bar
}, 10, 2); // 2 == amount of arguments expected
apply_filters('some_filter', 'foo', 'bar');
Because WP doesn't accept closures as callbacks (at least, certainly not for add_filter()) the short answer is "you can't". At least, not in a tidy way.
There are a couple of options here, depending on what you are doing. The first is the best, but you may not be able to use it:
Write a wrapper function that calls your function:
function gr_wp_list_pages_excludes_1 ($exclude_array) {
$custom_arg = 'whatever';
gr_wp_list_pages_excludes_1($exclude_array, $custom_arg)
}
This will only work if you are always passing the same custom argument in a given situation - you would write one of these wrapper functions for each different situation, and pass the name of the wrapper function to add_filter(). Alternatively, if you want it to be truly dynamic, you would need to...
Use a global variable: (Ref: Variable scope, $GLOBALS)
function gr_wp_list_pages_excludes($exclude_array) {
global $gr_wp_list_pages_excludes_custom_arg;
$id_array=$array('22');
$exclude_array=array_merge($id_array, $exclude_array);
return $exclude_array;
}
Using this approach means that you can pass any data you like into the function by assigning it to $gr_wp_list_pages_excludes_custom_arg in the global scope. This is generally regarded as bad practice and heavily frowned upon, because it makes for messy and unreadable code and leaves the memory space littered with extra variables. Note that I have made the variable name very long and specific to the function to avoid collisions - another problem with using global variables. While this will work, only use it if you absolutely have to.
Very simple!
add_filter('filter_name','my_func',10,3); //three parameters lets say..
my_func($first,$second,$third){
//............
}
then
echo apply_filters('filter_name',$a,$b,$c);
I have a page named ChangeApprovalInfo.php - It has a function called Row_Rendered as follows;
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$RecordOwner = $this->RequestUser->CurrentValue;
echo $RecordOwner;
}
Echoing $RecordOwner gets me the data I will need for a sql query on another page....
I have another page called ChangeApprovalEdit.php - This page has
<?php include_once "ChangeApprovalinfo.php" ?>
at the top of the file.
ChangeApprovalEdit.php has a function where I need the $RecordOwner variable as defined in ChangedApprovalInfo.php
If I add "echo $RecordOwner" on the ChangeApprovalEdit.php page, I get an error saying it's an unknown variable. My understanding is that I need to "make it global" or some such business. I know very little about PHP and the pages I am editing are long and complex. (to me, at least)
What do I need to do? I know that the information I have provided might not be enough to answer the question. I don't know enough to even know exactly what I need to ask. If more information is needed, I will edit and follow up.
pastebin of the files
ChangeApprovalInfo.php = http://pastebin.com/bSRM1wwN
ChangeApprovalEdit.php = http://pastebin.com/AStG9pqb
EDIT:
Changing Row_Rendered to this seems to be more effective. I'm having trouble seeing WHERE I can later echo this variable... but I'm getting somewhere with this...
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
Don't echo variables from functions, which just outputs them to the standard output. return them from the function so you can use the value elsewhere as well.
function Row_Rendered() {
$RecordOwner = $this->RequestUser->CurrentValue;
return $RecordOwner;
}
Then instead of
$obj->Row_Rendered();
use
echo $obj->Row_Rendered();
and if you want to use the value elsewhere, use
$value = $obj->Row_Rendered();
You can do a couple of things:
First, you can return $RecordOwner from the function, and store its value in a variable. This method is usually preferred.
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$RecordOwner = $this->RequestUser->CurrentValue;
echo $RecordOwner;
return $RecordOwner;
}
// Store it in a variable when calling the function.
$RecordOwner = Row_Rendered();
Or, you can make it global inside the function:
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
echo $GLOBALS['RecordOwner'];
}
You can use the $GLOBALS superglobals array, like this:
function Row_Rendered() {
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
However, you should not do that. Instead, refactor your application so that the view in ChangeApprovalinfo.php just contains a function, which is then called with the appropriate parameters.
EDIT: Chaning Row_Rendered to this seems to be more effective. I'm having trouble seeing WHERE I can later echo this variable... but I'm getting somewhere with this...
function Row_Rendered() {
// To view properties of field class, use:
//var_dump($this-><FieldName>);
$GLOBALS['RecordOwner'] = $this->RequestUser->CurrentValue;
}
I feel compelled to write another answer to this update. Let me demonstrate the use of globals as seen from outside that function:
$obj->Row_Rendered();
$obj->foobar();
echo $GLOBALS['RecordOwner'];
Quick, what will be echoed and where does that value come from? Well, it depends on what $obj-foobar() does. Maybe it changes the global variable. Maybe it doesn't. Who knows if the variable has been set at all? How would you trace back what happened exactly without adding a debug line after every single function call?
And that's just three lines of code. Imagine that in an application of any complexity.
Now, the same thing if I return the value from Row_Rendered:
$owner = $obj->Row_Rendered();
$obj->foobar();
echo $owner;
If the Row_Rendered method is behaving as it should (returning the owner), this code is very predictable. If you do not follow this pattern, you'll have a hell of a time getting anything done when the application grows to any halfway complex size.
Set the variable as global from within the function
$my_global_var = "old value";
function doing_stuff(){
global $my_global_var; //this will use the global variable instead of creating a local one
$my_global_var = "new value";
}
echo $my_global_var;//returns "new value"