I have come across the following statement from php manual
The following things can be passed by reference:
Variables, i.e. foo($a)
New statements, i.e. foo(new foobar())
References returned from functions, i.e.
And here's an example that doesn't work:
<?php
function foo(&$var)
{
$var++;
}
function bar()
{
$a = 5;
return $a;
}
foo(bar());
I am trying to understand why it doesn't work.
bar() returns '5' by value, which foo() references, so why does PHP doesn't permit this behavior?
Is this related to this excerpt from manual:
No other expressions should be passed by reference, as the result is
undefined. For example, the following examples of passing by reference
are invalid
However, to me this doesn't make sense because, bar() returns an actual value, not undefined.
Only variables should be passed by reference, so this will work
function foo(&$var)
{
$var++;
}
function bar()
{
$a = 5;
return $a;
}
$a = bar();
foo($a);
var_dump($a);
There is nothing wrong... here is your example a bit more completed.
function foo(&$var)
{
$var++;
return $var;
}
function bar()
{
$a = 5;
return $a;
}
echo foo($a=bar())."\n";
echo $a . "\n";
It outputs the expected.
6
5
On PHP 5.6.3
Related
As PHP manual states
Note: You should never use parentheses around your return variable when returning by reference, as this will not work. You can only return variables by reference, not the result of a statement. If you use return ($a); then you're not returning a variable, but the result of the expression ($a) (which is, of course, the value of $a).
I can not understand why not while the following code examples will give the same result.
The code with return $var:
<?php
function a(&$a) {
$a .= "c";
return $a;
}
$b = "b";
echo a($b);
echo $b;
?>
The code with return ($var):
<?php
function a(&$a) {
$a .= "c";
return ($a);
}
$b = "b";
echo a($b);
echo $b;
?>
The examples you show are Passing by Reference, where you pass a reference of a variable to a function. The quote from the manual is about Returning References of a variable in a function.
Just like you can't pass an expression by reference, you can't return an expression by reference, and wrapping a variable in () turns it in to an expression.
Passing a Reference
function a(&$b) { $b = 1; }
$x = 0;
a($x);
echo $x; // echos 1, because a reference to $x was changed
However a(abs($x)); or even a( ($x) ); generates:
Strict Standards: Only variables should be passed by reference
Returning a Reference
class a {
public $c = 0;
public function &b() { return $this->c; }
}
$a = new a;
$x = &$a->b();
$a->c = 1;
echo $x; // echos 1, because $x is a reference to $a->c that was changed
However, return ( $this->c ); generates:
Notice: Only variable references should be returned by reference
The example you give is not about returning references, but is an example of passing references.
function myfunc(&$arg) {
// here $arg has been passed by reference, nothing to do with the docs you quoted
}
The docs are about this:
function & myfunc($arg) {
// here you create your $result using $arg and whatever
return $result; // this will work
return ($result); // this will NOT
}
// and how you use it
$res =& myfunc(1);
You're modifying the variable, because it's passed by reference. But then you're setting it to the value that's returned by the function. That's why you're getting the same result.
When modifying a variable by reference, you don't need to return it. Your function will still have the same result if you write it like this:
function a(&$a) {
$a .= "c";
}
When you pass any value to the function, php copy the value and return a copy, not the variable you passed to the function. So if you want to change value and don't want to return anything from the function you need to declare, functions argument as reference - it means that any variable that you will pass to the function wont be copied by php and manipulation inside the function will change variable outside the function, for example:
$var = 1;
//not reference function
function notReference($argument)
{
$argument++;
}
notReference($var);
echo $var; // you will get 1
function reference(&$argument)
{
$argument++;
}
reference($var)
echo $var; // you will get 2,
$a = true;
1,new test($a);
2,new test(true);
Is there a difference between them(1,2), if have,what's of it? thank you,.
Well the other one uses a variable and the other one doesn't. This causes a fatal error in this case:
class test {
public function __construct( &$a )
{
}
}
$a = true;
new test($a);
new test(true); //Fatal error because this cannot be passed by reference
Strictly speaking, it depends on how test is defined.
If test is defined such that input parameters are passed by reference, then 2 would raise a fatal error, since true is a literal value.
Also, test could have side effects that mean that the order in which you execute lines 1 and 2 matter.
It depends on the constructor of the test class. In a regular pass-by-value constructor they are exactly the same:
class test {
public $b;
function __construct($a) { $this->b = $a; }
}
Here, $obj->b will be true for both your statements, as expected.
If, on the other hand, you are passing by reference you may get different results if you change the global $a later on. Example:
class test {
public $b;
function __construct( &$a ) { $this->b = &$a; }
}
$a = true;
$obj = new test($a);
$a = false;
$obj->b will be false in this case because it is a reference to $a! With references, you can also do it the other way around, changing $a from within the constructor:
class test {
function __construct( &$a ) { $a = false; }
}
$a = true;
$obj = new test($a);
$a will now be false even in the global scope!
In addition, new test(true) is not possible to do when passing by reference because you cannot have a reference to a literal value, only to other variables.
I don't understand what's going on with this. I need to call Func1 from Func2 and parametr for Func1 should be given inside the object.
class MyClass {
function Func1($a) {
return $a;
}
function Func2() {
echo $this->Func1($a);
}
}
$c = new MyClass();
$c->Func1('parametr'); // prints: 1
$c->Func2();
What about setting the parameter as class variable (property)?
class MyClass {
private $a;
function Func1($a) {
$this->a = $a;
return $a;
}
function Func2() {
echo $this->Func1($this->a);
}
}
This sets the parameter first time you call Func1. Then everytime you call Func2, it uses the parameter. You can also skip passing the parameter like this:
class MyClass {
private $a;
function Func1($a = null) {
if ($a === null) {
return $this->a;
} else {
$this->a = $a;
return $a;
}
}
function Func2() {
echo $this->Func1();
}
}
I.e if you call func1 without any parameter, it uses the stored variable (property), otherwise it uses the given parameter. This can be used in various ways depending on your exact needs.
The instruction:
echo $this->Func1($a);
is wrong: the variable $a is out of the scope of Func2. $a is a parameter of Func1 so is only int he scope of Func1.
You should read more about variable scopes at PHP http://php.net/manual/en/language.variables.scope.php
quick glimpse:
1) you can have global variables. to access those, use keyword global in functions that need access to that
2) you can have local variables, available only within a scope of a function
3) you can pass references to variables, so that variable from one scope is made accessible to other function/scope
4) you can have objects's internal variables of different kind (private, public, protected, static)
I suggest you get familiar with this stuff real well.
As for you code, problem is obvious. In Func2 the $a is local variable, thus when passed to $this->Func1($a), it is undefined. As your example code suggests, you might want to introduce class property private $a, and then use that. e.g.:
class X {
private $a;
function set($val){
$this->a = $val;
}
function get(){
return $this->a;
}
function doSomethingWithA(){
$this->set($this->get() * 2);
}
}
For some reason this function won't return the value ciao:
$a = "ciao";
function a() {
return $a;
}
I have no idea why.
Functions can only return variables they have in their local space, called scope:
$a = "ciao";
function a() {
$a = 'hello`;
return $a;
}
Will return hello, because within a(), $a is a variable of it's own. If you need a variable within the function, pass it as parameter:
$a = "ciao";
function a($a) {
return $a;
}
echo a($a); # "ciao"
BTW, if you enable NOTICES to be reported (error_reporting(-1);), PHP would have given you notice that return $a in your original code was using a undefined variable.
In PHP, functions don't have access to global variables. Use global $a in body of the function or pass the value of $a as parameter.
$a is not in scope within the function.
PHP does not work with a closure like block scope that JS works with for instance, if you wish to access an external variable in a function, you must pass it in which is sensible, or use global to make it available, which is frowned on.
$a = "ciao";
function a() {
global $a;
return $a;
}
or with a closure style in PHP5.3+
function a() use ($a) {
return $a;
}
Is it possible to access outer local varialbe in a PHP sub-function?
In below code, I want to access variable $l in inner function bar. Declaring $l as global $l in bar doesn't work.
function foo()
{
$l = "xyz";
function bar()
{
echo $l;
}
bar();
}
foo();
You could probably use a Closure, to do just that...
Edit : took some time to remember the syntax, but here's what it would look like :
function foo()
{
$l = "xyz";
$bar = function () use ($l)
{
var_dump($l);
};
$bar();
}
foo();
And, running the script, you'd get :
$ php temp.php
string(3) "xyz"
A couple of note :
You must put a ; after the function's declaration !
You could use the variable by reference, with a & before it's name : use (& $l)
For more informations, as a reference, you can take a look at this page in the manual : Anonymous functions
You must use the use keyword.
$bar = function() use(&$l) {
};
$bar();
In the very very old PHP 5.2 and earlier this didn't work. The syntax you've got isn't a closure, but a definition of a global function.
function foo() { function bar() { } }
works the same as:
function foo() { include "file_with_function_bar.php"; }
If you execute function foo twice, PHP will complain that you've tried to re-define a (global) function bar.
You can read default value by:
function(){
return preg_match(
"yourVar = \d+"
, str_file_get_contents(functionFile)
, arrayToPutFieldsValue
);
}
If You would use two functons in the same time - it's like someone's using a spoon and You want to take a food from that spoon - You'll waste a food or some of You will starv.
Anyway - You would have to set a pointer somehow in a hard way.
It's impossible to get any field from other function or class without calling it to life.
Functions/methods are instance-like - they need to be called.
Share the common fields by accessing a global fields with synchronized functions.
function a()
{
function val1($arg=null)
{
static $a;
if ($arg !== null) $a = $arg;
else return $a;
}
function b()
{
val1('1234');
echo val1() . '<br>'; // shows: 1234
val1('my custom data');
echo val1() . '<br>'; // shows: my custom data
}
b();
}
a();
Used val1('my custom data') to set my value
Used val1() to get my value