2

I need to modify some variables in the same way. For example I need to multiply each variable with 2 when some conditions met. Like this:

$a = 10;
$b = 100;
$c = 1000;
$d = 10000;

if($someCondition) {
    $a *= 2;
    $b *= 2;
    $c *= 2;
    $d *= 2;
}

Here I want to call a function to apply the change to all variables instead of multiplying one by one. I tried using a callback function like this (writing such function for this type of simple calculations may look silly, but I have more complex things to do, just keeping it simple here for better understanding):

Trial 1

function multiply_vars(&$a,&$b,&$c,&$d) {
    foreach(func_get_args() as $val) {        
        $val *= 2;
    }
}

if($someCondition) {
    multiply_vars($a,$b,$c,$d);
}

This works, but I need to know exactly how many variables I am passing to the function and set each variable as reference with &. For example, the above function will give me incorrect result when I pass 5 variables to modify.

Trial 2

function multiply_vars() {
    foreach(func_get_args() as $varname) {
        global $$varname;
        $$varname *= 2;
    }
}

if($someCondition) {
    modify_vars('a','b','c','d');
}

This works in a global context. But the problem is, I am doing this inside a class function where global $$varname refers to a variable outside my class function.

Is there any other way for achieving my purpose?

Note: I don't want to put my variables into an array. I know, it can be better solved by array_map() function, if it was in an array.

  • 1
    Why don't you just pass them in as an array, return the array, and then parse them when they return? – Jeremy Jackson Jan 09 '16 at 04:12
  • @JeremyJackson, I need to modify the original variables. Can you better post your suggestion as an answer with codes, so that I can better understand how it will achieve my purpose? – Tᴀʀᴇǫ Mᴀʜᴍᴏᴏᴅ Jan 09 '16 at 04:16
  • Do as JJ said, and use an array. Send it as an argument, and have some function/method do the work, and return the results which can update your global scope. – user1032531 Jan 09 '16 at 04:18

5 Answers5

3

You want a variadic argument list
Here's an example of passing a variable number of arguments to a function by reference:
PHP: variable-length argument list by reference?

Copied and Pasted from the above link:

Example 1:

function foo(&...$args) {
    $args[0] = 'bar';
}
foo($a);
echo $a, "\n";
#  output:
#a

Example 2:

function number(&...$args) {
    foreach ($args as $k => &$v) {
        $v = $k;
    }
}
number($zero, $one, $two);
echo "$zero, $one, $two\n";
#  output:
#0, 1, 2
Magical Gordon
  • 404
  • 2
  • 8
1

I realize that you said you do not want to put the variables in an array. However, you could potentially pass an array of references to avoid the additional value copy. E.g.

<?php
$a = 10;
$b = 100;
$c = 1000;
$d = 10000;

function multiply_vars($args) {
    foreach($args as &$arg) $arg *= 2;
}

multiply_vars([&$a, &$b, &$c, &$d]);

However, if you're using PHP 5.6 I think Magical Gordon's updated answer is a better solution.

kevinAlbs
  • 1,114
  • 2
  • 11
  • 20
0

I'd just pass them in as an array. For example:

$variables = array(
    'a' => 10,
    'b' => 100,
    'c' => 100,
    'd' => 1000,
);

function multiply_vars($variables) {
    $returnValues = array();
    foreach($variables as $key => $value) {        
        $newValue = $value * 2;
        array_push($returnValues, array($key => $newValue));
    }
    return $returnValues;
}

if($someCondition) {
    $variablesWithNewValues = multiply_vars($variables);
    //do stuff with  $variablesWithNewValues
}
Jeremy Jackson
  • 2,247
  • 15
  • 24
0

Your need tells that your strategy is not correct. And even if it worked, your code readability and maintenability will not be good! Anyway, I suggest that you create a function instead of your procedure, which you may call whenever needed and replace the original variable with the output.

An Example:

Function doStuff ($input){
    treat_input;
    Return output;
 }

$x = doStuff ($×);
 ....

Well, I know you will need to call this function as many times as number of variables you have. But trust me, this is the way that you have to go according to long experience in maintaining scripts.

Yazid Erman
  • 1,166
  • 1
  • 13
  • 24
0

Expanding on the other answers here, why not use an object? I'm assuming your question is a simplistic case, but there are a few benefits: objects are always passed by-reference, and the values assigned to an object's properties can be themselves accessed by-reference.

For example:

$numbers = new \StdClass();
$numbers->a = 10;
$numbers->b = 100;
$numbers->c = 100;
$numbers->d = 100;

You'd then use $numbers->a instead of $a in the global scope -- or use another variable by reference $a = &$numbers->a;

function multiply(StdClass $numbers, $multiple = 2)
{
    // Iteration isn't directly achievable with StdClass but...
    foreach (get_object_vars($numbers) as $key => $value) {
        $numbers->$key *= $multiple;
    }
}

And finally, our conditional:

if (true === myCondition) {
    multiply($numbers);
}
solocommand
  • 328
  • 1
  • 10
  • Pls check my note at the bottom of the question, I want to use my original variables, not an array or object. Otherwise, I would simply solve my problem with an array and modifying with `array_map()` function. (Also to note, I will need to modify different variables based on different conditions.) – Tᴀʀᴇǫ Mᴀʜᴍᴏᴏᴅ Jan 09 '16 at 04:49
  • See the answer from Magical Gordon then; a variadic function definition with the argument passed by reference would support both an arbitrary number of arguments, and allow the values to be returned back to the calling scope. – solocommand Jan 09 '16 at 04:54