How does the '&' symbol in PHP affect the outcome? - php

I've written and played around with alot of PHP function and variables where the original author has written the original code and I've had to continue on developing the product ie. Joomla Components/Modules/Plugins and I've always come up with this question:
How does the '&' symbol attached to a function or a variable affect the outcome?
For instance:
$variable1 =& $variable2;
OR
function &usethisfunction() {
}
OR
function usethisfunction(&thisvariable) {
{
I've tried searching through the PHP manual and other related sources but cannot find anything that specifically addresses my question.

These are known as references.
Here is an example of some "regular" PHP code:
function alterMe($var) {
$var = 'hello';
}
$test = 'hi';
alterMe($test);
print $test; // prints hi
$a = 'hi';
$b = $a;
$a = 'hello';
print $b; // prints hi
And this is what you can achieve using references:
function alterMe(&$var) {
$var = 'hello';
}
$test = 'hi';
alterMe($test);
print $test; // prints hello
$a = 'hi';
$b &= $a;
$a = 'hello';
print $b; // prints hello
The nitty gritty details are in the documentation. Essentially, however:
References in PHP are a means to access the same variable content by different names. They are not like C pointers; instead, they are symbol table aliases. Note that in PHP, variable name and variable content are different, so the same content can have different names. The closest analogy is with Unix filenames and files - variable names are directory entries, while variable content is the file itself. References can be likened to hardlinking in Unix filesystem.

<?php
$a = "hello"; # $a points to a slot in memory that stores "hello"
$b = $a; # $b holds what $a holds
$a = "world";
echo $b; # prints "hello"
Now if we add &
$a = "hello"; # $a points to a slot in memory that stores "hello"
$b = &$a; # $b points to the same address in memory as $a
$a = "world";
# prints "world" because it points to the same address in memory as $a.
# Basically it's 2 different variables pointing to the same address in memory
echo $b;
?>

It is a reference. It allows 2 variable names to point to the same content.

Related

PHP For/Foreach passed by reference at the end of for end the reference. [duplicate]

I have the code below. I want to change $b to use it again with values. If I do so it changes $a as well. How can I assign a value to $b again after previously assigning it as a reference to $a?
$a = 1;
$b = &$a;
// later
$b = null;
See explanation inline
$a = 1; // Initialize it
$b = &$a; // Now $b and $a becomes same variable with
// just 2 different names
unset($b); // $b name is gone, vanished from the context.
// But $a is still available
$b = 2; // Now $b is just like a new variable with a new value.
// Starting a new life.
$a = 1;
$b = &$a;
unset($b);
// later
$b = null;
The answer by #xdazz is correct, but just to add the following great example from the PHP Manual which gives an insight into what PHP is doing under the hood.
In this example you can see that $bar within the function foo() is a static reference to a function scope variable.
Unsetting $bar removes the reference but doesn't deallocate the memory:
<?php
function foo()
{
static $bar;
$bar++;
echo "Before unset: $bar, ";
unset($bar);
$bar = 23;
echo "after unset: $bar\n";
}
foo();
foo();
foo();
?>
The above example will output:
Before unset: 1, after unset: 23
Before unset: 2, after unset: 23
Before unset: 3, after unset: 23
First of all: Creating a reference from $a to $b creates a connection (for the lack of a better word) between the two variables, so $a changing when $b changes is exactly the way it is meant to work.
So, assuming you want to break the reference, the easiest way ist
unset($b);
$b="new value";

Smarty assignByRef inside loop

I need to render some Smarty template for different values inside a loop (a PHP loop, not a Smarty foreach), in the following way (just an example):
$a = 0;
$b = 0;
$output = "";
$tmpl = "$a, $b";
$smarty->assignByRef('a', $a['a']);
$smarty->assignByRef('b', $b['b']);
for (int i = 0; i < 10; ++i) {
++$a;
++$b;
$output .= $smarty->fetch("string:" . $tmpl);
}
My doubt is about assignByRef. The Smarty v3 docs says:
With the introduction of PHP5, assignByRef() is not necessary for most
intents and purposes. assignByRef() is useful if you want a PHP array
index value to be affected by its reassignment from a template.
Assigned object properties behave this way by default.
but I don't fully understand what does that technical note means. So, can I use assignByRef that way or not? or using just assign will produce the same output?
PHP 4 objects were passed by value, unless the user explicitly specified the reference by prepending ampersand: &$variable. For this reason, function arguments that were likely to consume a big amount of memory were passed by reference in order to optimize memory usage:
function f(&$huge) {
// ...
}
PHP 5 variables are passed by reference, even if the user did't specify it explicitly (the ampersand character is not used). By assigning one variable to another we only create a new container (internally called zval) for the same data in memory. Consider this:
$a = new stdClass;
$b = $a;
The first line allocates memory for variable $a and an object of stdClass, and stores the object's identifier into the variable. The second line allocates memory for variable $b, stores the object's identifier into the $b variable, and increments an internal reference counter. The reference counter value shows how many times the object is referenced in the code. When $b variable is destroyed, the reference counter is decremented by one. When the value of reference counter becomes equal to zero, the object's memory is deallocated. The following code demonstrates the idea:
$a = new stdClass;
debug_zval_dump($a);
$b = $a;
debug_zval_dump($a);
$c = $a;
debug_zval_dump($a);
$c = null; // destroy $c
debug_zval_dump($a);
$b = null; // destroy $b
debug_zval_dump($a);
Output
object(stdClass)#1 (0) refcount(2){
}
object(stdClass)#1 (0) refcount(3){
}
object(stdClass)#1 (0) refcount(4){
}
object(stdClass)#1 (0) refcount(3){
}
object(stdClass)#1 (0) refcount(2){
}
But when a variable is modified, PHP versions 5 and 7 create a copy of the variable in order to keep the original value (variable) intact.
$m1 = memory_get_usage();
$a = str_repeat('a', 1 << 24);
echo number_format(memory_get_usage() - $m1), PHP_EOL;
// 16,781,408
$b = $a;
$c = $a;
echo number_format(memory_get_usage() - $m1), PHP_EOL;
// 16,781,472
$b[0] = 'x';
echo number_format(memory_get_usage() - $m1), PHP_EOL;
// 33,562,880
$c[0] = 'x';
echo number_format(memory_get_usage() - $m1), PHP_EOL;
// 50,344,288
The same is applied to the context of the function arguments. Thus, if a variable is supposed to be used for read only, there is no need for passing it by reference explicitly. The words in the Smarty documentation mean that in most cases, you pass variables to the templates, and usually do not expect the template to change them. You need to pass a variable by reference only when you really want the variable to be modified in the template. The same concept is applied to any function arguments in PHP 5 and newer.

How to use a pointer in a PHP function? [duplicate]

This question already has answers here:
Are there pointers in php?
(9 answers)
Closed 7 years ago.
In C we can use pointer for a function parameter:
test( *text);
function test( *txt){
//codes goes here
}
Is it possible in PHP?
Variable names in PHP start with $ so $entryId is the name of a variable.
$this is a special variable in Object Oriented programming in PHP, which is reference to current object.
-> is used to access an object member (like properties or methods) in PHP, like the syntax in C++.
So your code means this: place the value of variable $entryId into the entryId field (or property) of this object.
The & operator in PHP, means pass reference. Here is an example:
$b=2;
$a=$b;
$a=3;
print $a;
print $b;
// output is 32
$b=2;
$a=&$b; // note the & operator
$a=3;
print $a;
print $b;
// output is 33
In the above code, because we used & operator, a reference to where $b is pointing is stored in $a. So $a is actually a reference to $b.
There is a good explanation of pointers on this page
There are references, but that's not the same as pointers.
php.net has multiple pages explaining What References Are, What References Do and What References Are Not.
There too, it is mentioned multiple times that
References are not pointers.
They provide a way to assign $a to $b so that if you reassign $b, $a changes as well:
$a = 'a';
$b = &$a; // Reference
$b = 'b'; // Now $a == 'b'
This can be used for function arguments as well:
function myFunc(&$b)
{
$b = 'b';
}
$a = 'a';
myFunc($a); // Now $a == 'b'
Before PHP 5.3.0 is was also possible to do a thing called "call-time pass-by-reference", where you would have a "normal" function declaration and use the & operator in the call instead:
function myFunc($b)
{
$b = 'b';
}
$a = 'a';
myFunc(&$a); // As of PHP 5.3.0 produces a Fatal Error, saying:
// Call-time pass-by-reference has been removed; If you would like to pass argument by reference, modify the declaration of myFunc().
But beware! Assigning another reference will not update the original reference:
$a = 'a';
$b = 'b';
$c = &$a;
$c = &$b; // $a == 'a'
[ Demo ]
A trap resulting from that exists with the global keyword.
$a = 'a';
$b = 'b';
function myFunc()
{
global $a, $b;
$a = &$b;
var_dump($a);
}
myFunc(); // 'b'
var_dump($a); // 'a'
That is because global $a effectively means $a = &$GLOBALS['a'], so assigning it a new reference will not update $GLOBALS.
Of course you can prevent that by using $GLOBALS directly.
But if you're using globals at all, you should probably rethink your design anyway.
With references, there is now also a difference between setting a variable = NULL and using unset().
= NULL follows references, unset() does not:
$a = 'a';
$b = &$a;
unset($b); // $a == 'a'
$a = 'a';
$b = &$a;
$b = NULL; // $a == NULL
[ Demo ]
Bottom line:
References allow for things that wouldn't be possible without them, but sometimes do not behave the way one would expect them to, because of how PHP was built.

PHP, $this->{$var} -- what does that mean?

I have encountered the need to access/change a variable as such:
$this->{$var}
The context is with CI datamapper get rules. I can't seem to find what this syntax actually does. What do the {'s do in this context?
Why can't you just use:
$this->var
This is a variable variable, such that you will end up with $this->{value-of-$val}.
See: http://php.net/manual/en/language.variables.variable.php
So for example:
$this->a = "hello";
$this->b = "hi";
$this->val = "howdy";
$val = "a";
echo $this->{$val}; // outputs "hello"
$val = "b";
echo $this->{$val}; // outputs "hi"
echo $this->val; // outputs "howdy"
echo $this->{"val"}; // also outputs "howdy"
Working example: http://3v4l.org/QNds9
This of course is working within a class context. You can use variable variables in a local context just as easily like this:
$a = "hello";
$b = "hi";
$val = "a";
echo $$val; // outputs "hello"
$val = "b";
echo $$val; // outputs "hi"
Working example: http://3v4l.org/n16sk
First of all $this->{$var} and $this->var are two very different things. The latter will request the var class variable while the other will request the name of the variable contained in the string of $var. If $var is the string 'foo' then it will request $this->foo and so on.
This is useful for dynamic programming (when you know the name of the variable only at runtime). But the classic {} notation in a string context is very powerful especially when you have weird variable names:
${'y - x'} = 'Ok';
$var = 'y - x';
echo ${$var};
will print Ok even if the variable name y - x isn't valid because of the spaces and the - character.

php variable $a contains variable $b in it update $b and $a should automatically update

I have two variables in PHP, say $a and $b. $a is a string variable. It contains $b. I want to update $a automatically if $b is updated.
$b = 4;
$a = "value is ".$b;
echo $a; // value is 4
$b = 5;
echo $a; // should print value is 5
Yes, $a can be updated automatically if you assign $b to $a by reference, but there should not be any string concatenation assigned to $a.
Try:
$b = 4;
$a = &$b;
$c = 'Value is ';
echo $c.$a;
$b = 5;
echo $c.$a;
Here is a demo
Not possible the way you want it. You see, variables can be passed by reference, like so:
$a = &$b;
Which will cause $a to automatically update when $b changes, however, it may not contain any other value, (like the string you want), so you'll have to use a function or another variable to do it.
$b = &$a;
echo "Value is $b";
or
$b = &$a;
$description = "Value is ";
echo $description . $b;
PHP doesn't have that feature. Related features you could use are:
References, which let you alias one variable to another. The value of each variable is the same, since they're simply symbol table aliases.
$b = "I'm b."
$a =& $b;
echo $a;
Variable variables, in which one variable holds the name of the other.
$b = "I'm b."
$a = 'b';
echo $$a;
However, variable variables should generally be avoided as they generally cause needless obfuscation.
Functions (as mithunsatheesh suggests). This is closest to what you want, as a function call is an expression that will have the value you're looking for. The only place a function wouldn't work where a variable would is when interpolating the value into a double-quoted string or a heredoc. Instead, you'd have to use string concatenation, or assign the result of the function call to a local variable and interpolate that.
You should pass it by reference. How to do it ?
Make a function:
function showValue(&$b)
{
return 'value is ' . $b;
}
echo showValue($b);
I think this should work.
Take a look at http://www.php.net/manual/en/language.references.whatdo.php
$a = 4;
$b =& $a;
$a = 5;
echo $b; // should print 5;
When a php script runs it runs "line after line". When you assign like this
$b = 4;
$a = "value is ".$b;
Value of $b is already assigned to $a as a integer 4 (not $b). So, if next $b is updated to some other value. Variable $a has no idea about it.
In this kind of case you have to use function or variable reference as describe in some other answers
$a = 4;
$b =& $a;
$a = 5;
echo $b;

Categories