PHP: Array passed by reference to a function? - php

I have this php function that has to perform some processing on a given array:
processArray($arrayToProcess) {
$arrayToProcess['helloStackOverflow'] = TRUE;
}
Later, the code invokes the following:
$niceArray = array('key' => 'value');
processArray($niceArray);
The key 'helloStackOverflow' isn't available outside the processArray function. I tried calling the following:
processArray(&$niceArray);
Using "&" helps, however it raises some warning:
Deprecated function: Call-time pass-by-reference has been deprecated; If you would like to pass it by reference, modify the declaration of populateForm_withTextfields()
Tried the & in there, but that just stops the code.
How should I do this?

You have to define the reference in the function, not in the call to the function.
function processArray(&$arrayToProcess) {

processArray(&$arrayToProcess) {
$arrayToProcess['helloStackOverflow'] = TRUE;
}
implements the reference in PHP way.
See http://fi2.php.net/references for useful information about references.

processArray(&$arrayToProcess) {
$arrayToProcess['helloStackOverflow'] = TRUE;
}
Referencing passing now takes place at the function declaration, not when the function is called.
http://php.net/manual/en/language.references.pass.php
for full documentation.

Related

PHP 5.4 Anonymous Function in Array undefine

This is PHP 5.4 code...
<?php
function abc($YesNo){return $YesNo["value"];}
$YesNo = array("value"=>"No","text"=>"No");
$x = array("active"=>function(){return abc($YesNo);});
echo $x['active']();
?>
Notice: Undefined variable: YesNo on line 7
Output Should be : Yes
if i directly put array in code by replace $YesNo like
<?php
function abc($YesNo){return $YesNo["value"];}
$x = array("active"=>function(){return abc(array("value"=>"Yes","text"=>"Yes"));});
echo $x['active']();
?>
output : Yes
which is correct output. Now what's the problem in first code. I need that for re-usability
Try this,
You can use use for passing data to a closure.
<?php
function abc($YesNo){return $YesNo["value"];}
$YesNo = array("value"=>"No","text"=>"No");
$x = array("active"=>function() use ($YesNo) {return abc($YesNo);});
echo $x['active']();
?>
You provide your anonymous function with a parameter:
$x = array("active"=>function($param){return abc($param);});
then you call it:
echo $x['active']($YesNo);
You may use the use keyword to make your function aware of an external variable:
$x = array("active"=>function() use ($YesNo) {return abc($YesNo);});
but it would be quite against the idea of reusability, in this case.
The problem is that your variable is not accessible within the function due to Variable Scope.
Because the array is defined outside of the function, it is not by default available inside the function.
There's a couple of solutions
Disclaimer: These are intended to fit within the scope of the question. I understand that they are not necessarily best practice, which would require a larger discussion
First Option:
You can declare the array within the function, like below. This is useful if you don't need access to it outside of the function.
function abc($YesNo){
$YesNo = array("value"=>"No","text"=>"No");
return $YesNo["value"];
}
Second Option:
Within your abc function, you can add the line global $YesNo. This is useful if you do need access to the array outside of the function:
function abc($YesNo){
global $YesNo;
return $YesNo["value"];
}
Other options exist (such as moonwave99's answer).
Finally:
Why are you putting an anonymous function within the array of $x? Seems like a path that will lead to problems down the road....
Your variable $YesNo needs to be visible in the scope of your anonymous function. You need to add global $YesNo as the first statement in that function:
So
$x = array("active"=>function(){return abc($YesNo);});
becomes
$x = array("active"=>function(){global $YesNo; return abc($YesNo);});
... also "value"=>"No" should be "value"=>"Yes" if you want it to return "Yes"

Only variables should be passed by reference

I have a class:
class Validator {
private $validationArray;
private $cleanedValues;
public function __construct($arg1, $arg2=NULL) {
if(empty($arg2)) {
$this->LoadValidatorByName($arg1);
} else {
$this->LoadValidatorFromLeadType($arg1, $arg2);
}
}
private function LoadValidatorFromLeadType($lead_type, $vocabulary) {
$ErrorReporter = new ErrorReporter;
$taxonomy_term = reset(taxonomy_get_term_by_name($lead_type, $vocabulary));
...some more stuff
The function taxonomy_get_term_by_name is a Drupal function but the issue I am experiencing is a PHP one.
When this method is called PHP complains with:
Strict warning: Only variables should be passed by reference in Validator->LoadValidatorFromLeadType() (line 32 of [path to my file])
Line 32 is ths line with:
$taxonomy_term = reset(taxonomy_get_term_by_name($lead_type, $vocabulary));
I've looked in to the error and I'm pretty sure I know what it means, but I can't understand what is wrong with my code that causes this warning.
reset is waiting for a variable reference. You are passing it a function result...
$taxonomy_term = taxonomy_get_term_by_name($lead_type, $vocabulary);
$taxonomy_term = reset($taxonomy_term );
This mean that only variable should be passed by reference, not an expression.
reset($array_variable); // correct
and
reset(some_function_that_returns_array()); // incorrect
If you take a second and think about it more - you would find that reset() with expression (not a variable) makes no sense, because you've rewind the array pointer to the beginning, but you don't have the ability to access that array anymore.
You should only reset a variable (which is passed by reference), not a return value of a function.
see: http://www.php.net/reset

PHP. Pass variable by reference vs string. How to works with these two different arguments?

I'm writing my own debug functions and I need some help to fix the code below.
I'm trying to print a variable and its name, the file where the variable and the function was declared and the line of the function call. The first part I did, the variable, the variable name, the file and the line is printed correctly.
At the code, a($variable) works good.
The problem is I'd like this function accepts a string too, out of a variable. But PHP returns with a fatal error (PHP Fatal error: Only variables can be passed by reference in ...). At the code, a('text out').
So, how can I fix this code to accept a variable or a string correctly?
code (edited):
function a(&$var){
$backtrace = debug_backtrace();
$call = array_shift($backtrace);
$line = $call['line'];
$file = $call['file'];
echo name($var)."<br>".$var."<br>".$line."<br>".$file;
}
$variable='text in';
a($variable);
a('text out');
I need pass the variable by reference to use this function below (the function get the variable name correctly, works with arrays too):
function name(&$var, $scope=false, $prefix='unique', $suffix='value'){
if($scope) $vals = $scope;
else $vals = $GLOBALS;
$old = $var;
$var = $new = $prefix.rand().$suffix;
$vname = FALSE;
foreach($vals as $key => $val) {
if($val === $new) $vname = $key;
}
$var = $old;
return $vname;
}
The way your code is currently implementing pass by reference is perfect by design, but also by design cannot be changed to have two a() methods - one accepting a variable by reference and the other as a string-literal.
If the desire to pass a string literal instead of assigning it to a variable first is really needed, I would suggest creating a second convenience method named a_str() that actually accepts a string-literal instead of a variable by reference. This method's sole-purpose would be to relay the variable(s) to the original a() method - thereby declaring a variable to pass by reference.
function a_str($var) {
a($var);
}
The only thing to remember is, use a($variable); when passing by reference and a_str('some text'); when not.
Here is the same convenience-method for your name() function:
function name_str($var, $scope=false, $prefix='unique', $suffix='value'){
return name($var, $scope, $prefix, $suffix);
}
The only way to do what you are asking without writing an additional function like #newfurniturey suggests is plain and simply opening and parsing the file where your function was called as text (e.g. with fopen), using the data from debug_backtrace. This will be expensive in terms of performance, but it might be ok if used only for debugging purposes; and using this method you will no longer need a reference in your function, which means you can freely accept a literal as the parameter.

Access array returned by a function in php

I'm using a template engine that inserts code in my site where I want it.
I wrote a function to test for something which is quite easy:
myfunction() { return '($this->data["a"]["b"] ? true : false)'; }
The problem is, $this->data is private, and I can't access it everywhere, so I have to use getData(); which causes my problem.
$this->getData()['a']['b']
does not work, and assigning the value first doesn't either because it will be used directly in an if() block.
Any ideas?
Since PHP 5.4 it's possible to do exactly that:
getSomeArray()[2]
Reference: https://secure.php.net/manual/en/language.types.array.php#example-62
On PHP 5.3 or earlier, you'll need to use a temporary variable.
You cannot use something like this :
$this->getData()['a']['b']
ie, array-access syntax is not possible directly on a function-call.
Youy have to use some temporary variable, like this :
$tmp = $this->getData();
$tmp['a']['b'] // use $tmp, now
In your case, this probably means using something like this :
function myfunction() {
$tmp = $this->getData();
return ($tmp['a']['b'] ? true : false);
}
You have to :
first, call your getData() method, and store its return value in a temporary varibale
then, use that temporary variable for your test
You don't have much choice about that, actually...
Ok... apparently there really isn't a better way, so I'm going to answer myself with a not so beautiful solution:
I created the function:
arrayGet($array, $index) { return $array[$index]; }
And used it like this:
myfunction() { return '(arrayGet(arrayGet($this, "a"), "b") ? true : false)' }
This is not pretty but works.
$this->data is always accessible, if it is protected. $object->data is not accessible from everywhere, so if you're returning $this in your code, and it is evaluated as such, it should be ok.
Btw, there is a bug in your code: The quotes need to be escaped.
myfunction() { return '($this->data[\'a\'][\'b\'] ? true : false)'; }
It is possible from PHP version 5.4.
If you don't want a temporary variable for that and your PHP version is less, than 5.4, than you still can use a few built in functions to get the first or the last element:
$x = 'first?last';
$first = array_shift(explode('?', $x));
$last = end(explode('?', $x));
$last2 = array_pop(explode('?', $x));
Edit:
!!! Please note, that in later versions( 5.4+ ) PHP will throw a notice, because end only expects variables as parameter.

Is it possible to pass parameters by reference using call_user_func_array()?

When using call_user_func_array() I want to pass a parameter by reference. How would I do this. For example
function toBeCalled( &$parameter ) {
//...Do Something...
}
$changingVar = 'passThis';
$parameters = array( $changingVar );
call_user_func_array( 'toBeCalled', $parameters );
To pass by reference using call_user_func_array(), the parameter in the array must be a reference - it does not depend on the function definition whether or not it is passed by reference. For example, this would work:
function toBeCalled( &$parameter ) {
//...Do Something...
}
$changingVar = 'passThis';
$parameters = array( &$changingVar );
call_user_func_array( 'toBeCalled', $parameters );
See the notes on the call_user_func_array() function documentation for more information.
Directly, it may be impossible -- however, if you have control both over the function you are implementing and of the code that calls it - then there is one work-around that you might find suitable.
Would you be okay with having to embed the variable in question into an object? The code would look (somewhat) like this if you did so.
function toBeCalled( $par_ref ) {
$parameter = $par_ref->parameter;
//...Do Something...
$par_ref->parameter = $parameter;
}
$changingVar = 'passThis';
$parembed = new stdClass; // Creates an empty object
$parembed->parameter = array( $changingVar );
call_user_func_array( 'toBeCalled', $parembed );
You see, an object variable in PHP is merely a reference to the contents of the object --- so if you pass an object to a function, any changes that the function makes to the content of the object will be reflected in what the calling function has access to as well.
Just make sure that the calling function never does an assignment to the object variable itself - or that will cause the function to, basically, lose the reference. Any assignment statement the function makes must be strictly to the contents of the object.
This works by double referencing,the original variable is modified when the $parameter variable is modified.
$a = 2;
$a = toBeCalled($a);
echo $a //50
function toBeCalled( &$par_ref ) {
$parameter = &$par_ref;
$parameter = $parameter*25;
}
Except you are using deprecated functionality here. You'll generate a warning in PHP5 making it less than perfect.
Warning: Call-time pass-by-reference has been deprecated; If you would like to pass it by reference, modify the declaration of runtime function name. If you would like to enable call-time pass-by-reference, you can set allow_call_time_pass_reference to true in your INI file in ...
Unfortunately, there doesn't appear to be any other option as far as I can discover.

Categories