passing variable names as string - php

I'm trying to perform the same function dosomething() to multiple variables $lastsum $avatar $angels $city $square in PHP.
$lastsum->dosomething();
$avatar->dosomething();
$angels->dosomething();
$city->dosomething();
$square->dosomething();
Is there a way to make this code cleaner by listing the names of the variables in a string array and perform the function with a for loop. I'm looking for something like this. Does anyone know the right way to do this in PHP?
$all = ['lastsum' , 'avatar', 'angels' , 'city' , 'square'];
foreach (....){
$(nameofvariable)->dosomething();
}

What's wrong with
$all = array($lastsum , $avatar, $angels, $city, $square);
foreach (....){
$variable->dosomething();
}
To achieve exactly what you're looking for, use variable variables
$all = array('lastsum' , 'avatar', 'angels' , 'city' , 'square');
foreach ($all as $x) {
$$x->dosomething();
}
Many people consider this to be bad style though.

Not an elegant solution. However, you could make use of eval():
$all = array( 'lastsum' , 'avatar', 'angels', 'city', 'square' );
foreach ( $all as $var ) {
$code = "\$${var}->dosomething();";
eval($code);
}
Otherwise, store the objects in an array:
$all = array( $lastsum , $avatar, $angels, $city, $square );
foreach ( $all as $obj ) {
$obj->dosomething();
}

If you want to use variables variables, it would be more like this:
function dosomething(&$var) {
$var .= 'bar';
}
$a = 'foo';
$b = 'bar';
$vars = array('a', 'b');
foreach ($vars as $var) {
dosomething($$var);
}
var_dump($a); // foobar
var_dump($b); // barbar
If $a is an object, then you can do $$var->dosomething().
EDIT: NOTE: In most cases, if you have to use variables variables, you may want to consider using a proper data structure instead, like an array.

Another alternative:
$all = array('lastsum' , 'avatar', 'angels' , 'city' , 'square');
foreach ($all as $x) {
$GLOBALS[$x]->dosomething();
}
Not sure if you could do method calls from the GLOBALS superglobal, but you could most likely access static properties/functions.

Related

return multiple variables as array and extract them

I have a function that get data from a table and there are multiple columns (variables). I need to return all the variables from the function to use them.
I've tried multiple ways but I can't make it work:
return array($var, $var2, $var3, $etc);
return compact($var, $var2, $var3, $etc);
Now I use extract() but I'm doing something wrong:
$data = $functions->my_function($id);
// I must check first if there are results
// will this work?
if (is_array($data)) {
extract($data);
// now I can use the variables from the function:
echo $var, $var2, $var3, $etc;
}
Instead of declaring the variables one by one:
$var = $data[0];
$var2 = $data[1];
Maybe the problem are the variables names?
$stmt->bind_result($id, $use, $type, $status, $bhk, $baths, $area_1, $area_2, $city, $zone, $sale_price, $monthly_price, $description);
I read something about wrong variable names won't work with extract() in the php.net comments.
The reason your extract is not working is because you need to return an associative array. You can do this manually, or you can use compact properly by passing variable names, not variable values:
function my_function() {
$var = 'Happy';
$var2 = 'New';
$var3 = 'Year';
return array(
'var' => $var,
'var2' => $var2,
'var3' => $var3
// ... etc ...
);
// Alternate method, with compact
return compact('var', 'var2', 'var3');
}
$values = my_function();
extract($values);
echo $var; // outputs 'Happy'
echo $var2; // outputs 'New'
echo $var3; // outputs 'Year'
Edit
Extract is not best-practice. When reading the code, it's a mystery where the variables suddenly appear from, and makes it more difficult to maintain.
Better would be to check / get the values explicitly from the array:
$values = my_function();
$var = $values['var'];
$var2 = $values['var2'];
$var3 = $values['var3'];
echo $var; // outputs 'Happy'
echo $var1; // outputs 'New'
echo $var3; // outputs 'Year'
Depending on the structure of your code, you have to decide if you can rely on that function to always return those values, or if you need to check them. If you need to check multiple keys / values, then I typically like to write a utility function for that sort of thing:
function get_val( $key, $array, $default = FALSE) {
$array = (array)$array;
return ( isset( $array[ $key ] ) ) ? $array[ $key ] : $default;
}
Then, you'd use it like so:
$values = my_function();
$var = get_val( 'var', $values );
$var2 = get_val( 'var2', $values );
$var3 = get_val( 'var3', $values );
echo $var; // outputs 'Happy'
echo $var1; // outputs 'New'
echo $var3; // outputs 'Year'
Lastly, your function that returns the row from the DB should probably be responsible for doing the validation / returning something meaningful. For example, if no rows, then return FALSE, then you can check like so:
function my_function( $id ) {
// your code to get the row based on the id
// then, check that a row was returned...
if ( ! count( $row ) ) {
return FALSE;
} else {
// return the row
}
}
$values = my_function();
if ( $values !== FALSE ) {
// do stuff, because we know we have a valid row
}

Shortcut to isset() and assigning values

Is there a shortcut method to assigning $_GET['values'] to variables?
I currently do like others do:
if(isset($_GET['type'],$_GET['case'])
$type = $_GET['type'];
$case = $_GET['case'];
Is there a cleaner method to do this instead of doing like below separately.
$type = $_GET['type'];
$case = $_GET['case'];
http://docs.php.net/extract
I think you're looking for extract function.
extract($_GET); //now, all of the functions are in current symbol table
Well, with array map you can you get the case not just once, but all at once, and you can also check for isset() and empty() at the same time too.
Suppose, you have this URL: read.php?id=1&name=foo&job=student&country=Brazil
Your problem is fetching the $_GET type, and you may need to check if is it empty/isset or not right?
Well, first you create a function to iterate through it.
function checkGet($val){
return (isset($val) && !empty($val)) ? $val : null;
}
Then, you callback that function with array_map()
$check = array_map('checkGet', $_GET);
And that is it!
If you were to do var_dump($check); now, you would get get all the types, and values:
array (size=4)
'id' => string '1' (length=1)
'name' => string 'foo' (length=3)
'job' => string 'student' (length=7)
'country' => string 'Brazil' (length=6)
Meaning, after this, instad of doing:
if(isset($_GET['something']) && !empty($_GET['something']))
$var = $_GET['something'];
echo $var;
Just do:
echo $check['something']
The only one-line code I can think of, to make sure that you still do the necessary checks, is
$type = (isset($_GET['type'])) ? $_GET['type'] : 'a default value or false';
Reading comments, I understand you may want to do this:
foreach($_GET as $key=>$value) {
$$key = $value;
}
I would suggest though, to always initialize the variables you need only. The above code will result in getting unknown variables, which may actually give the user a way to manipulate your script.
Example:
index.php?ExpectedVar=1&UserDefinedVar=2
will generate the following variables in your code:
$ExpectedVar // 1 <- you wanted this one
$UserDefinedVar // 2 <- but what about this?
What if you had this script called by some other script?
Then even if you have this code at the top of your file, you may have some variables overwritten from a user defined $_GET!
Disaster case Scenario:
script1.php
<?php
$tableToDelete = "old_products";
include("script2.php");
?>
script2.php
<?php
foreach($_GET as $key=>$value) {
$$key = $value;
}
// user added &tableToDelete=users
// DROP TABLE $table
// will gloriously delete users
?>
Instead by writing a few lines with the original code I posted, you can get the variables you need at the start of your php script and use them with a clear mind.
Try like
foreach($_GET as $key=>$value) {
$get_arr[$key] = $_GET[$key];
}
print_r($get_arr);
I would do it that way, this way you make sure that it will only return TRUE or FALSE
if (!isset($_GET['type']) || empty($_GET['type'])) {
// Display error
} else {
$type = $_GET['type'];
$case = $_GET['case'];
}
Or you can do it that way as well
$type = (isset($_GET['type'])===false)?'':trim($_GET['type']);
$case = (isset($_GET['case'])===false)?'':trim($_GET['case']);
$_GET is table, so you can easy use foreach function
For example
foreach ($_GET as $key => $value) {
... = $value;
}
If you would like to create variables with $key names use variable variables
PHP Manual Variable Variables
You can do it through extract()
extract($_GET, EXTR_PREFIX_ALL, 'g');
so that
$_GET['val'] becomes $g_val
Note the third parameter: g it prepends g_ to the keys.
This (untested) class should help you:
class MyGet {
public static $myValues = array();
public static function setMyValues($keywords, $where) {
MyGet::$myValues = array();
for ($index = 0; $index < count($keywords); $index++) {
if ((!(isset($where[$keywords[$index]]))) || (empty($where[$keywords[$index]]))) {
MyGet::$myValues = array();
return false;
}
MyGet::$myValues[$keywords[$index]] = $where[$keywords[$index]];
}
}
}
You can use it like this:
if (MyGet::setMyValues(array(0 => "type", 1 => "case"), $_GET)) {
//the values are initialized
} else {
//the values are not initialized
}

Assigning values to a large number of variables in php after an if ()

Do you know a better way to do thing when it comes to assigning values to a large number of variables after an if?
In my case it like this:
$akeType = array_key_exists('type',$handle);
$akeParent = array_key_exists('parent',$handle);
$akeUserName = array_key_exists('userName',$handle);
$akeUserId = array_key_exists('userId',$handle);
$akeCountryCode = array_key_exists('userId',$handle);
if ( $akeType && $akeParent && $akeUserName && $akeUserId & $akeCountryCode ) {
$listType = $handle['type'];
$listParent = $handle['parent'];
$listUserName = $handle['userName'];
$listUserId = $handle['userId'];
$foo = $_POST['foo'];
$bar = $_POST['bar'];
$listCountryCode = $handle['countryCode']; // Is there a way to clean up this part? The assignments to variables.
take a look at the extract -- Import variables into the current symbol table from an array
extract($handle, EXTR_OVERWRITE, "ake_");
You can do this with the somewhat more obscure code following:
$keys= array('type','parent','userName', 'userId');
foreach($keys as $key) {
$nametoset= "list".ucfirst($key);
$$nametoset= $handle[$key];
}
$$nametoset refers to the variable named like the string $nametoset.
Similar code may be used for the $ake... variables.
You can use Variable variables to set your variable list.
For your specific case, you can use the following code:
foreach ($handle as $key => $value) {
$var_name = 'list'.$key;
$$var_name = $value;
}
foreach ($_POST as $pkey => $pvalue) {
$$pkey = $pvalue;
}
These loops create variables depending on your arrays keys.

compact() variables into array by prefix?

Is this possible?
Like make an array with all the variables that have a certain prefix?
I don't need the keys just the values, but I guess I could use array_values on the array.
If you need to do this, it's probably not written very well to begin with, but, here's how to do it :)
$foobar = 'test';
$anothervar = 'anothertest';
$foooverflow = 'fo';
$barfoo = 'foobar';
$prefix = 'foo';
$output = array();
$vars = get_defined_vars();
foreach ($vars as $key => $value) {
if (strpos($key, $prefix) === 0) $output[] = $value;
}
/*
$output = array(
'test', // from $foobar
'fo', // from $foooverflow
);
*/
http://php.net/manual/en/function.get-defined-vars.php
my eyes are bleeding a little, but I couldn't resist a one liner.
print_r(iterator_to_array(new RegexIterator(new ArrayIterator(get_defined_vars()), '/^' . preg_quote($prefix) . '/', RegexIterator::GET_MATCH, RegexIterator::USE_KEY)));
If you're talking about variables in the global scope, you could do this with $GLOBALS[]:
$newarray = array();
// Iterate over all current global vars
foreach ($GLOBALS as $key => $value) {
// And add those with keys matching prefix_ to a new array
if (strpos($key, 'prefix_' === 0) {
$newarray[$key] = $value;
}
}
If you have lots and lots of variables in global scope, this is going to be slower in execution than manually adding them all to compact(), but faster to type out.
Addendum
I would just add (though I suspect you already know) that if you have the ability to refactor this code, you are better off to group the related variables together into an array in the first place.
This, my second answer, shows how to do this without making a mess of the global scope by using a simple PHP object:
$v = new stdClass();
$v->foo = "bar";
$v->scope = "your friend";
$v->using_classes = "a good idea";
$v->foo_overflow = "a bad day";
echo "Man, this is $v->using_classes!\n";
$prefix = "foo";
$output = array();
$refl = new ReflectionObject($v);
foreach ($refl->getProperties() as $prop) {
if (strpos($prop->getName(), $prefix) === 0) $output[] = $prop->getValue($v);
}
var_export($output);
Here's the output:
Man, this is a good idea!
array (
0 => 'bar',
1 => 'a bad day',
)

php function with arrays

I want to pass one argument to a function, rather than multiple arguments, that tend to grow unexpectedly. So I figure an array will get the job done. Here's what I've drafted so far...
<?php
function fun_stuff($var){
// I want to parse the array in the function, and use
}
$my = array();
$my['recordID'] = 5;
$my['name'] = 'John Smith';
$my['email'] = 'john#someemail.com';
echo fun_stuff($my);
?>
I haven't quite grasped the concept of parsing an array. And this is a good way for me to learn. I generally pass the same variables, but on occasion a record does not have an email address, so I do need to make a condition for missing keys.
Am I doing this right so far? Can I pass an array as an argument to a function?
And if so, how do I parse and search for existing keys?
Hopefully this isn't too far off topic...but you sounded like you were just trying to avoid multiple parameters when some can be NULL. So, I would recommend that you use an object instead of an array for clarity...that way, there is no confusion as to what properties should exist. If you're using PHP 5, you can also strongly type the parameter so nothing else can get in. So:
class Record {
public $Id;
public $Name;
public $Email
}
function fun_stuff( Record $record ) {
// you will now have better intellisense if you use an IDE
// and other develoers will be able to see intended parameters
// clearly, while an array would require them to know what's
// intended to be there.
if( !empty($record->Email) ) {
// do whatever.
}
}
Yes you are on the right track. The approach I take is put required paramters as the first parameters and all optional parameters in the last argument which is an array.
For example:
function fun_stuff($required1, $required2, $var = array()) {
// parse optional arguments
$recordId = (key_exists('recordID', $var) ? $var['recordId'] : 'default value');
$name = (key_exists('name', $var) ? $var['name'] : 'default value');
$email = (key_exists('email', $var) ? $var['email'] : 'default value');
}
Then you can call your function like so:
fun_stuff('val 1', 'val 2', array(
'recordId' => 1,
'name' => 'John',
'email' => 'john#stackoverflow.com'
));
This is a bad design practice, but that's not the question here. You can "parse" array's like so...
if( array_key_exists( 'email', $var ))
{
// use email field
}
If you need to, you can loop through all elements like so...
foreach( $var as $key => $value )
{
echo '$var[\''.$key.'\'] = '.$value;
}
I'm not recommend you to use array for this.
You can define optional arguments with default values:
//$name and $email are optional here
function fun($record_id, $name='', $email='')
{
if (empty($name)) print '$name is empty';
}
//Usage:
fun(5, 'Robert');
fun(5);
fun(5, 'Robert', 'robert#gmail');
fun(3,'','robert#gmail');
If you will use array, IDE will not be able to show autocomplete suggestions, it means more typos, and you have to remember all keys of this array forever or look at code of the function each time.
I'm not really sure what you want to achieve, but I suspect something like this:
$aPersons = array();
$aPersons[] = array('name' => 'name1', 'age' => 1);
$aPersons[] = array('name' => 'name2', 'age' => 2);
array_map('parsePerson', $aPersons);
function parsePerson($aPerson) {
echo $aPerson['name'];
echo $aPerson['age'];
}
The problem with your current array is that it only has one dimension.
You can simple do echo $my['name'];. There are easier ways to parse arrays though.
foreach($aPersons as $aPerson) {
echo $aPerson['name'];
echo $aPerson['age'];
}
$iLength = sizeof($aPersons);
for($i = 0; $i <= $iLength; $i++) {
echo $aPersons[$i]['name'];
echo $aPersons[$i]['age'];
}
To parse and view, there is the signficant print_r function which gives out the array details.
When calling a function you need the return syntax at the end that will parse out anything you call in the return.
You obviously can pass array to the function. Inside it read the variable as you were assigning values before it. If you assign:
$my['key'] = 'value';
In you function use:
echo $var['key'];
Why you don't use a foreach to walk in array?
function fun_stuff($var){
foreach($var as $key => $item){
echo '[', $key, "] => ", $item, "\n";
}
}
$my = array();
$my['recordID'] = 5;
$my['name'] = 'John Smith';
$my['email'] = 'john#someemail.com';
fun_stuff($my);
Yes, this is correct (though your question is a bit broad). You're already referencing the array values via indexes when you set up the $my variable. You can do the same thing within your function (with the $var variable).
I recommend taking a look at all of PHP's built-in array functions: http://php.net/manual/en/ref.array.php
Try this:
function fun_stuff($var){
// I want to parse the array in the function, and use
$fun_string = "";
if( is_array( $var ) {
if( array_key_exists( "name", $var ) )
$fun_string .= "For " . $var["name"];
else $fun_string .= "A nameless one ";
if( array_key_exists( "email", $var ) )
$fun_string .= " (email: " . $var["email"] . ")";
else $fun_string .= " without a known e-mail address";
if( array_key_exists( "recordID", $var ) )
$fun_string .= " has record ID of " . $var["recordID"];
else $fun_string .= " has no record ID set";
$fun_string .= "\n";
}
return $fun_string;
}
Yes You can! Just pass the array and inside the function just use a foreach loop to parse it!
function myFunction($array)
{
foreach($array as $value)
{
echo $value;
}
}
or If you want to have full control over the pair key/value:
function myFunction($array)
{
foreach($array as $key=>$value)
{
echo "key:".$array[$key]."value:".$values;
}
}

Categories