I found this PHP code in an app I have to modify...
$links = mysql_query($querystring);
foreach (mysql_fetch_array($links) as $key=>$value)
{
$$key = $value;
}
I'm a bit stumped.
Is it really iterating over the query results and copying the value into the key?
If so, what would be the point of this?
Also, what is the double $$ notation? I've not seen this before in PHP and I can't seem to find reference to it on the PHP site. Is it a typo? It doesn't seem to be affecting the code. I don't want to go "fixing" anything like this without understanding the consequences.
The $$ isn't a typo; it's how you interact with a variable named by another variable. Like if you do
$varname = 'foo';
$$varname = 'bar';
you've just set $foo to 'bar'.
What the loop is doing is expanding the row contents into the current variable namespace, kind of like extract(). It's a terrible way to do it, not least because it's also iterating over the numeric indices.
You generally see that written like this.
$links = mysql_query($querystring);
while ($row = mysql_fetch_array($links))
{
echo $row['id'];
}
The $$ is what's called a variable variable.
It looks like it's essentially making the keys as vars holding the value. Sort of what register_globals does to the POST/GET etc vars. I wouldn't recommend doing it this way. I dare say it will lead to problems, like overwriting vars, and unexpected vars being available.
It's creating key-value pairs based on the sql query results and result structure.
As for the $$, it's just another variable, except this time it's the result that's set to a variable.
$key = "hello";
$$key = "hi";
echo $key;
output is: "hi"
The $$ will reference the variable with the name stored in the first variable. So for example:
$var='some';
$some=15;
echo $$var;
That will print 15. It takes $vara and gets 'some', so then it takes that as a variable name because of the second $ and it prints the value of $some which is 15.
So basically that code is copying the values into a variable that has the same name as the key.
Related
So I am writing this php function which reads a csv file and assigns every column to a variable. In the end it needs to calculate the mean of a row. I would like to pass the row (from which the mean has to calculated) in the parameters.
My question is how do I pass a variable name (including the dollar sign) of a variable of the function?
I've tried several things like:
function("$number") //this just says the variable is undefined, which is true
Same as above, but without the quotes, does the same thing of course...
function("\$number")
Not entirely sure what you're trying to do, but it sounds something like variable variables. So, if you have a variable $foo you would pass it like this: myfunc('foo'); Then myfunc might look something like this:
myfunc($var) {
global $$var;
// do stuff with $$var
}
You'd probably be better off just loading the columns into an array and looping over that in the function.
If I understood correctly, what you need is a variable variable:
$some = 'foo';
$name = 'some';
echo $$name; //displays 'foo'
As I understand, when you pass a variable to a function, and if you don't use reference sign (&) , it means any changes inside your function will not affect to your variable outside the function. In other words, it means the compiler will make a copy of the outside variable to use inside function, doesn't it?
But when I run these testing code, it does not happen like that.
Can anyone explain me what I miss here? Thank you
My test code: the expected result should be 3, but it becomes 1?
function test($arr2) {
foreach($arr2 as &$item) {
$item = 1;
}
}
$arr = array(2);
foreach($arr as &$item2) {
$item2 = 3;
}
test($arr);
print_r($arr);
This issue has been solved a few times before you've asked this (#1). The issue is due to the fact that:
Reference of a $value and the last array element remain even after the
foreach loop. It is recommended to destroy it by unset().
Reference: PHP foreach()
You need to unset the last $item2 after your foreach:
foreach ($arr as &$item2) {
$item2 = 3;
}
unset($item2);
This is quite interesting, it seems like the behavior of array are the same as objects in php in which new array still holds the copy of the members identifier (which points to the same value as the array it was copied from).
As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
PHP Manual - Objects and references
Even though you are not passing $arr as Reference variable, you are still accessing $arr elements as References in function test(). So anything that changes in function will effect outside function too.
If you are looking to change $arr ( which has been passed as $arr2 in test function ) only in test function, then remove &from $item
I have dynamically created an array and I want to extract the array and put each item into its own variable.
Here's my PHP:
$bar = $_POST['foo'];
extract($bar);
echo $1;
foo is an array from a form I made.
Whenever I run the script I get this error:
Parse error: syntax error, unexpected '1' (T_LNUMBER), expecting variable (T_VARIABLE) or '$' in /Application/...
When I change my code to:
$bar = $_POST['foo'];
extract($bar, EXTR_PREFIX_ALL, "bar_");
echo $bar_1;
I get the undefined variable error.
Please help me.
UPDATE:
My first code was informational, another person might come across this question with that problem not knowing what's wrong. The second piece of code is my actual code.
M intention is to input each array item into a different field in a mysql table. I haven't written the full code yet since this extract() thing doesn't seem to be working.
UPDATE 2:
$_POST['foo'] is an array of checkbox values
Variables in PHP cannot start with numbers:
echo $1;
That's invalid and will throw an error.
You're also using extract improperly in that you're using it on something that may or may not be an array. We have no guarantee that $_POST['foo'] is an associative array(and it's not), which is the only array type extract works on. extract uses the keys from the associative array to create the new variables.
$bar = $_POST['foo'];
extract($bar, EXTR_PREFIX_ALL, "bar_");
echo $bar_1;
From http://php.net/extract
Prefixes are automatically separated from the array key by an underscore character.
Your extracted variable is named $bar__1 (two underscores).
But listen to everyone who answered, "do not use extract() on untrusted data."
This is very unsafe.
You should not do it.
foreach($_POST['foo'] as $key=>$value) {
${"itemnumber".(string)$key} = $value;
}
Now you can acces $itemnumber2 ---> equals to the array item in the position 2
EDIT: I just tested it at writecodeonline.com and it works:
$arr = array('one', 'two');
foreach($arr as $key=>$value) {
${"itemnumber".(string)$key} = $value;
}
echo $itemnumber1; //echoes: two
Here you can see a similar case:
http://us2.php.net/manual/en/function.extract.php#60946
i know this
$var1 = "10";
$var2 = "var1";
then
echo $$var2 gives us 10
i want to this with array
i have array
$intake_arr = array(5=>10,7=>20,8=>30,9=>40,10=>50,11=>60,12=>70);
i have some logic that will pick one array from set of array , all array will look like $intake_arr
if i do this $target_arr = "intake_arr";
then can $$target_arr[5] will yield 10? i tried but i didnt that 10 value, how can i achieve this with array
Your statement ($$target_arr[5]) is ambiguous. PHP doesn't know what you actually want to say: Do you mean: use $target_arr[5]'s value and prepend the $, to use that as a variable, or do you want to use the value of $target_arr, and get the fifth element of that array?
Obviously it's the latter, but PHP doesn't know that. In order to disambiguate your statement, you have to use curly braces:
${$target_arr}[5];
That'll yield 10. See the manual on variable variables for details
Note:
As people said in comments, and deleted answers: variable variables, like the one you're using is risky business. 9/10 it can, and indeed should be avoided. It makes your code harder to read, more error prone and, in combination with the those two major disadvantages, this is the killer: it makes your code incredibly hard to debug.
If this is just a technical exercise, consider this note a piece of friendly advice. If you've gotten this from some sort of tutorial/blog or other type of online resource: never visit that site again.
If you're actually working on a piece of code, and you've decided to tackle a specific problem using variable vars, then perhaps post your code on code-review, and let me know, I'll have a look and try to offer some constructive criticism to help you on your way, towards a better solution.
Since what you're actually trying to do is copying an array into another variable, then that's quite easy. PHP offers a variety of ways to do that:
Copy by assignment:
PHP copies arrays on assignment, by default, so that means that:
$someArray = range(1,10);//[1,2,3,4,5,6,7,8,9,10]
$foo = $someArray;
Assigns a copy of $someArray to the variable $foo:
echo $foo[0], ' === ', $someArray[0];//echoes 1 === 1
$foo[0] += 123;
echo $foo[0], ' != ', $someArray[0];//echoes 123 != 1
I can change the value of one of the array's elements without that affecting the original array, because it was copied.
There is a risk to this, as you start working with JSON encoded data, chances are that you'll end up with something like:
$obj = json_decode($string);
echo get_class($obj));//echoes stdClass, you have an object
Objects are, by default, passed and assigned by reference, which means that:
$obj = new stdClass;
$obj->some_property = 'foobar';
$foo = $obj;
$foo->some_property .= '2';
echo $obj->some_property;//echoes foobar2!
Change a property through $foo, and the $obj object will change, too. Simply because they both reference exactly the same object.
Slice the array:
A more common way for front-end developers (mainly, I think, stemming from a JS habbit) is to use array_slice, which guarantees to return a copy of the array. with the added perk that you can specify how many of the elements you'll be needing in your copy:
$someArray = range(1,100);//"large" array
$foo = array_slice($someArray, 0);//copy from index 0 to the end
$bar = array_slice($someArray, -10);//copy last 10 elements
$chunk = array_slice($someArray, 20, 4);//start at index 20, copy 4 elements
If you don't want to copy the array, but rather extract a section out of the original you can splice the array (as in split + slice):
$extract = array_splice($someArray, 0, 10);
echo count($someArray);//echoes 90
This removes the first 10 elements from the original array, and assigns them to $extract
Spend some time browsing the countless (well, about a hundred) array functions PHP offers.
${$target_arr}[5]
PHP: Variable variables
Try this one:
$intake_arr = array(5=>10,7=>20,8=>30,9=>40,10=>50,11=>60,12=>70);
$target_arr = 'intake_arr';
print ${$target_arr}[5]; //it gives 10
For a simple variable, braces are optional.But when you will use a array element, you must use braces; e.g.: ${$target_arr}[5];.As a standard, braces are used if variable interpolation is used, instead of concatenation.Generally variable interpolation is slow, but concatenation may also be slower if you have too many variables to concatenate.Take a look here for php variable variables http://php.net/manual/en/language.variables.variable.php
I have several variables coming from an array in $POST_['array'] i wish to make some kind of loop for example foreach that makes, for every value in the variable a variable name of it and assigns the value for it.
For example if i have
$POST_['name'];
$POST_['last'];
$POST_['age'];
$POST_['sex'];
I want the loop to create each variable from the array inside the $_POST with the name of the variable like the following:
$name = 'John';
$last = 'Doe';
$age = '32';
$sex = 'male';
NOTE - The array is coming from a serialized jquery string that puts together all the variables and values in a form into one big string.
Is this possible?
You don't need a loop, you want extract:
extract($_POST); // But use caution, see below
Cautions and best practices
As noted in the comments this forces all parameters in the $_POST array into the current symbol space.
In global space
<?php
extract($_GET);
var_dump($_SERVER); // Can be overwritten by the GET param
?>
The code above illustrates the problem as shown in this answer — some pretty dangerous things can be overwritten in the global space.
Inside a function
function myFunc() {
// (Mostly) empty symbol space! (excluding super globals)
extract($_POST);
}
Inside a function, as the first line, no harm done.
Important note: You might think since $_SERVER is a super global, that this exploit could happen inside a function as well. However, in my testing, on PHP Version 5.3.4, it is safe inside a function — neither $_SERVER, $_POST, $_GET, $_SESSION, or presumably other superglobals, could be overwritten.
With options
You can also use extract with extract_type options that do not overwrite.
The best option to use, in my opinion, is simply to prefix all variables from extract:
// $_GET = test=1&name=Joe
extract($_GET, EXTR_PREFIX_ALL, "request_get");
echo $request_get_test; // 1
echo $request_get_name; // Joe
That way you don't have the overwrite problem, but you also know you got everything from the array.
Alternate - looping w/ conditional
If you wanted to do this manually (but still dynamically), or wanted to conditionally extract only a few of the variables, you can use variable variables:
foreach ($_POST as $key => $value) {
if (isset($$key)) continue;
$$key = $value;
}
(The example condition I've used is an overwrite prevention.)
Try not to use extract() when using $_POST. You may overwrite variables you want which will result in unpredictable behaviour. It is a bad habit to get into and while is dynamic may not be the best solution.
You can do something like this:
foreach($_POST as $key => $value)
{
switch($key)
{
case "name":
$name = $value;
break;
case "last":
$last = $value;
break;
}
}
You can actually use the built-in function called extract
Why not use a foreach?
foreach($_POST as $key=>$val){
${$key} = $val;
}
I just want to mention that you can improve foreach technique because we have in HTML the ability to name one of our form fields using square bracket notation, and if we do that, what HTML will do is it will submit a series of values as an array.
<input name="user[name]">
<input name="user[last]">
<input name="user[age]">
<input name="user[sex]">
Than use just one line of code to assign all values from input fields into local array $args.
$args = $_POST['user'];
So what that means is when we go to process the form, we're looking at an array of values instead of a bunch of single values that we have to go retrieve.
So we can just simply go to the post super global and ask for one item: that is user. And what we get back is an associative array. So instead of having to build up that array by going and retrieving all those values one at a time, we're instantly given an array, just because we named our form fields differently.