convert string into variable name - php

I am working on a function that takes a string as an argument, which I need to use to get the value of a variable of the same name.
For example
If the string $foo = "$_POST['email']"; is passed I need to retrieve the value of $_POST['email'] and store it as $example, so that $_POST['email'] == $example would return true. There is no feasable way of passing the value directly to function (the variable has to be dynamic to make the function worthwhile).
I did think of using variable variables but they don't work with super globals which will be the primary source of the values I need.
Basically is there a way to get the value of a variable (usually in a superglobal array) with the needed variable as a string?
Let me know if more detail is needed.
Thanks

Variable variables would be the answer, but if you're after fetching values from $_POST array, why not pass just a key to a function?
Note: ths function is provided just for example, my actual recommendation is below.
function fetchFromPost($key) {
if(isset($_POST[$key]) {
return $_POST[$key];
} else {
return null; //or do whatever you want to do in case key is not found
}
}
In fact filter_input(), which allows you to chose an input array, a key and a sanitaion filter to be used, is already there for you

It is possible, although I seriously doubt you should use this. It allows for PHP injection and makes your source code very vulnerable if you don't know where the string came from:
<?
function eval_expression($expression)
{
eval("\$temp = $expression;");
return $temp;
}
// Usage:
echo eval_expression("\$_GET['plop']");

Related

PHP problem with array_push(mainArr, subAssociativeArr) inside a function

the array_push(mainArr, subAssociativeArr) does not work when it is inside a function. I need some help with this code:
$store=array();
$samsung=array('id'=>'10','name'=>'samsung');
$sony=array('id'=>'11','name'=>'sony');
function addOne($store, $element){
array_push($store, $element);
}
addOne($store, $samsung);
var_dump($store); //output: empty array
however it works fine if without function; like the following:
$store=array();
$samsung=array('id'=>'10','name'=>'samsung');
$sony=array('id'=>'11','name'=>'sony');
array_push($store, $samsung);
var_dump($store); //output: array is added
so, what is the problem???
You forgot to return
function addOne($store, $element){
$store[]=$element;
return $store;
}
$store = addOne($store, $samsung);
You could also pass by reference if you want to (which is more in line with the code you have):
function addOne(&$store, $element){
$store[]=$element;
}
addOne($store, $samsung);
Note the &. Instead of copying the inputs, this is more like a pointer to the original variable, so you can update it directly. Ether way is fine here, it's a matter of developers choice really. For example it can be very easy to mix the two:
//Don't do this
function addOne(&$store, $element){ //returns null
$store[]=$element;
}
$store = addOne($store, $samsung); //sets $store to null
Which you probably don't want to do, so I can see an argument for both ways. Unless you have super big array, it probably doesn't matter much. It's very easy to forget that a random function is pass by reference.
So use whatever method makes more sense to you.
P.S. - I refuse to use array_push, it's ugly and I don't like it :). Doing $store[]=$element; is the same as array_push($store,$element), except it avoids an unnecessary function call.
Cheers.
When it's in a function, you have a different scope. While the parameters to your addOne function have the same name, they are actually copies of the variables passed, not references to them.
So when you array_push() in a function, you're only affecting the variables in that function's scope, not the outer scope.
You can either return $store, or pass the variables by reference.
If you want it to work within a function you need a reference to the variable. A reference in PHP is defined as & and they are similar to "pointers" in C or C++.
Try this:
function addOne(&$store, $element){
array_push($store, $element);
}
addOne($store, $samsung);
A PHP reference is an alias, which allows two different variables to write to the same value. 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.
http://www.php.net/manual/en/language.oop5.references.php

PHP Function pulling an array that matches the parameter

$youtubes = array("lNT4H39G2rw","pF2_qvdm8DQ","_8ytwhhJwco","K16ZRFWR2Mc","9WuPxe7zc6Q","rXZIIclPnd0","J8ZwyN6E3_Q","OEWJbsh0z-4","o62-X0stdFM","aIIiww2Neq0","5TJc-VbNYg0","MYQa1Tgw_z8","alxzFm-bqug","UmI7oyllrlY","RGKFXDHFmn4");
function randomFromArray($data) {
global $$data;
echo $$data[rand(0,count($youtubes)-1)];
}
randomFromArray("youtubes");
I am trying to get this to work as a function, so I can enter the array name as a parameter. It is then supposed to echo a random entry from the array. The bit where it gets the random entry from array works on its own if I substitute it straight in, but I can't seem to get it working as a function.
Any help?
You're using the variable name $youtubes in your randomFromArray function in the call to count (but the variable is not available under that name there).
Btw., why don't you pass in (a reference to) the array instead of its name? Would be much tidier than using global $$data; The following code uses a reference to avoid copying the array (but remember that then, the outside array could be changed from inside the method):
$youtubes = // ...
function randomFromArray(&$data) {
echo $data[rand(0,count($data)-1)];
}
randomFromArray($youtubes);
dont call the function randomFromArray("youtubes"); in this way you call the function with youtubes parametar like a string. and inside the function itself you dont have a $youtubes variable. call the function like this randomFromArray($youtubes);
hope this would help
You are passing the string 'youtubes' into the function, not the array. You want to pass in the name of the array:
randomFromArray($youtubes);
$youtubes = array("lNT4H39G2rw","pF2_qvdm8DQ","_8ytwhhJwco","K16ZRFWR2Mc","9WuPxe7zc6Q","rXZIIclPnd0","J8ZwyN6E3_Q","OEWJbsh0z-4","o62-X0stdFM","aIIiww2Neq0","5TJc-VbNYg0","MYQa1Tgw_z8","alxzFm-bqug","UmI7oyllrlY","RGKFXDHFmn4");
function randomFromArray($data) {
echo $data[rand(0,count($data)-1)];
}
randomFromArray($youtubes);
There are some things fundamentally wrong here.
global $$data
Why is there a double $ sign? And where would this data be coming from?
echo $$data[rand(0,count($youtubes)-1)];
Your function doesn't know the variable $youtubes, since you have never defined it inside of the function. All your function knows is the $data variable that you are passing to it.
randomFromArray("youtubes"); You are passing a string to your function, rather then your array. You probably want this instead:
randomFromArray($youtubes); // Pointing to your actual array, rather then a string
Try reading up on PHP functions first before attempting to use them as you're lacking a lot of basic knowledge about them.
After you put a ; after global $$data, you can try this: $f = $$data; and then echo $f[rand(..)]; if you really want to use names instead variables as others suggested. And if you do that you can use the string (or $f) further in the function code.

How do I get the name of a variable variable?

So, I need the actual variable name "varName" from global space. This function is actually a method inside a class.
Code is arbitrary for simplicity
$varName = 'what ever';
public function save($var)
{
$i[varName goes here] = $var;
}
I don't know if this is even possible, but I think maybe with a callback?
If it's a global variable, you might be able to find out the original name with:
$varname = array_search($var, $GLOBALS);
But that's not overly reliable; a best guess. If two global variables would contain the same value, you would just receive the name of either of them.
Read about $GLOBALS variable in the documentation.
This is probably what you need. Depending on the way you determine which variable you need, you can for example user array_search() to find the proper name based on the value.
Caution: $GLOBALS is about global scope's variables.
EDIT:
But this would be still a guess. You may try the following method to determine the name of the passed variable with ~100% certainty:
Pass variable to the method with reference.
Use array_search() for finding the name of the variable. If only one key matches it, you have your name. If not, go to the next step.
Save the initial value of the variable and save the list of positions at which you have found matching elements.
Change the variable's value into new one. Perform another search based on new value and get positions that are also in the list of positions from point no. 3.
At this point you have probably found the name of the variable you are looking for.
But...
Is it really needed? I suggest that you should look for simpler solution, some better encapsulation of your code.
Ps. array_search() actually returns no more than one key (see documentation). You should know that and make searching for multiple results a little more sophisticated to not skip the correct one if more than one variable matches your search criteria. (EDIT2: As mario suggested, array_intersect($GLOBALS, array($var)) will suffice)
In C, you would use a macro. I don't think there's an equivalent in PHP.
You could pass the name of the variable to the function as a string, then in the function get the variable's value from GLOBALS or eval it.
Thanks for the solution!
Here is my test:
<?php
$varName = 'what ever';
function save($var)
{
$i[array_search($var, $GLOBALS)] = $var;
print_r($i);
}
save($varName);
?>
prints:
Array
(
[varName] => what ever
)

PHP Variables made with foreach

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.

Using extract

I'm new to OOP and want to revamp this function to get rid of using globals.
function CatchListing() {
$parseform = array('itemnum','msrp','edprice','itemtype','box','box2','box25','box3','box4','box5','box6','box7','itemcolor','link');
foreach ($parseform as $globalName) {
$GLOBALS[$globalName] = mysql_real_escape_string($_POST[$globalName]);
}
}
I was told to use array_map & then extact, but I am not sure of how to structure this.
function CatchListing() {
$_POST['listing'] = array_map('mysql_real_escape_string', $_POST);
$nst = extract($_POST['listing']);
}
(listing is the form name btw)
Thanks
Be VERY careful about using extract with externally inputted values as from $_GET and $_POST.
you're much better off extracting the values manually to known values.
It's far too easy for an extract from _GET or _POST to clobber existing variables.
There are so many things to say and Jonathan makes a very good start. Every time the user has the opportunity to play with your internal data and you don't check them, there is a huge "opportunity" (depends on the view..) that something goes wrong. Here is another approach on how to "maybe" get where you want to go:
<?php
function Sanitize($string){
return mysql_real_escape_string(trim($string));
}
function CatchListing(){
foreach($_POST as $key => $value) {
$key = Sanitize($key);
$value = Sanitize($value);
if($key && $value && !$GLOBALS[$key]){ /* prevent overwriting existing globals*/
$GLOBALS[$key] = $value;
}
}
}
global $nice;
$nice = "working";
CatchListing();
print_r($GLOBALS);
?>
To be honest, it still has not really anything to do with OOP and furthermore should be seen as a procedural approach. Personally I would use an additional and reusable function to "sanitize" the input, because you never know, if someday you want to change your database or the "escape" function and then you exactly know where to look for possible changes. Ah one more thing: Are you certain that you don't know all the possible names of all the variables you have to expect? Maybe you can predetermine them and put them in another array and check each user supplied argument with in_array.
To completely get rid of the usage of globals in your code, and also to make it much better overall, you can do something along these lines:
stop using $_POST, as it's a superglobal. When code needs values from superglobals, pass them as parameters
don't store values into $GLOBALS. If you need to return more than one value, consider returning an object or an array
Here's how I think I would modify your code to improve it:
function CatchListings($listings) {
$filteredListings = array_map('mysql_real_escape_string', $listings);
//I assume you only need the values in the array in the original snippet,
//so we need to grab them from the parameter array and return only that
$requiredListings = array();
$requiredKeys = array('itemnum','msrp','edprice','itemtype','box','box2','box25','box3','box4','box5','box6','box7','itemcolor','link');
foreach($requiredKeys as $key) {
$requiredListings[$key] = $filteredListings[$key];
}
return $requiredListings;
}
To use this function, you simply do $result = CatchListings($_POST);. Same result, no globals used.
There is one thing to consider, though. It may not be best possible form to just pass a randomly filled array (ie. $_POST) to the function, and expect it to contain specific keys (ie. $requiredKeys array). You might want to either add logic to check for missing keys, or process the post array before passing it.

Categories