How to use a pointer in a PHP function?
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
References are not pointer in php?
In simple words, references are aliases.
A variable in PHP is stored in two pieces: the name and the value. The name points to the value.
$x = 2;
$y = $x;
$z = &$x;
When $x = 2;
is executed, the name x
is stored in the symbol table of the current scope and the value 2
is stored in a zval
(don't ask, it's the internal name of a data structure that stores a value in PHP).
When $y = $x;
is executed, the name y
is stored in the symbol table of the current scope and the value of $x
(2
) is copied into a new zval
structure.
When $z = &$x;
is executed, the name z
is stored in the symbol table of the current scope but a new zval
is not created. Instead, z
is set to point to the same zval
as x
.
The memory used by the variables $x
, $y
and $z
looks like this:
+---------+ +---------+
| x | -------------> | 2 |
+---------+ +---------+
^
+---------+ | +---------+
| y | -------------------------> | 2 |
+---------+ | +---------+
|
+---------+ |
| z | --------------------+
+---------+
When a value is passed by reference to a function or a function returns a reference the same things happen, only the names are stored in different symbol tables (remark the "current scope" in the explanation above).
Let' see this code:
function f(& $z) {
$y = $z;
$z = $z + 2;
}
$x = 2;
f($x);
After $x = 2;
the memory looks like this:
+---------+ +---------+
| x | -------------> | 2 |
+---------+ +---------+
During the execution of function f()
, the memory looks like this:
+===== global ====+
| +---------+ | +---------+
| | x | -------------> | 4 |
| +---------+ | +---------+
+=================+ ^
|
+====== f() ======+ |
| +---------+ | | +---------+
| | y | -------------------------> | 2 |
| +---------+ | | +---------+
| | |
| +---------+ | |
| | z | --------------------+
| +---------+ |
+=================+
y
and z
are stored in a different symbol table than x
and they are removed (together with the entire symbol table that contains them) when the call to f()
returns.
When y
is removed, its value is also removed because there is no name that points to it any more. But, because the value pointed by z
is also pointed by x
($z
is an alias), the value is not removed together with z
and it survives the function call. f()
modifies the value using $z
; and this change is visible in the main program through the variable $x
.
The things happen in a similar way when a function returns a reference. The function returns a value that is not copied but a new name that points to it is created into the symbols table of the calling code.
PHP behavior and arrays pointers
This behavior is characteristic of language?
The meaning of "pointer" in PHP arrays is not the same as the general meaning of "pointer" (in C/C++ or other languages that gives the programmer direct access to memory).
There are no pointers in PHP. The array data type keeps internally a cursor inside the list of values it contains. It is called the internal pointer of the array and it is modified by functions reset()
, next()
, prev()
, end()
, each()
and maybe others. It can be used to iterate over the array like this:
$array = array(1, 2, 3);
while (list($key, $val) = each($array)) {
echo($key.' => '.$val."\n");
}
There is no reliable way to iterate the array using next()
or prev()
because they return FALSE
when there are no more elements to iterate but they also return FALSE
when the value FALSE
is stored as an element in the array.
They could be useful if you need to analyze only several items from the beginning (or end) of the array. F.e. let's say we have an array of integers returned by a function and we need to get the first value that is not zero.
But this goal can be accomplished even easier using foreach()
:
$array = array(0, 0, 0, 2, 0, 1, 0, 3);
foreach ($array as $val) {
if ($val != 0) {
break;
}
}
echo($val); // prints "2"
or array_shift()
:
$array = array(0, 0, 0, 2, 0, 1, 0, 3);
do {
$val = array_shift($array);
if ($val != 0) {
break;
}
} while(count($array));
echo($val); // prints "2"
The result is expected: the pointer has been reset. My question is if the pointer is reset only after the end of the array?
The documentation of foreach()
is wrong. Maybe it was correct on PHP 3 and PHP 4 but I think since the introduction of iterators in PHP 5 the behaviour of foreach()
changed (to better).
It says:
When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop.
As foreach relies on the internal array pointer, changing it within the loop may lead to unexpected behavior.
A simple test contradicts this statement:
$array = array(1, 3, 5, 7, 9);
foreach ($array as $val1) {
foreach ($array as $val2) {
echo('$val1='.$val1.'; $val2='.$val2.'; ');
}
echo("\n");
}
It works without problems. It should not work if foreach()
is using the internal array pointer. It probably creates a copy of the pointer.
You can also try to use current()
, next()
, prev()
or reset()
inside the foreach()
and you will get surprising and sometimes inconsistent results.
You better use foreach()
to iterate over the arrays and do not rely on the internal pointer in any way.
The functions reset()
and end()
are, however, very handy when you need to get the first and the last element of the array without worrying about the keys.
PHP - can a method return a pointer?
PHP doesn't have pointers. PHP has reference. A reference in PHP is a true alias. But you don'tneed them. Objects are passed by handle (so they feel like references) for other data PHP uses a copy-on-write mechanism so there is no memory/performance penalty. The performance penalty comes when using references as they disable copy-on-write and therefore all the optimizations in the engine.
If you really want to return a reference youhave todeclare it in the signature:
public function &prepare( $query ) {
// bla bla bla
return $this->statement;
}
But as said: If $this->statement is an object there is no need.
See also http://php.net/references
PHP pointers vs references
In PHP, there are no pointers, only references. Your examples demonstrate pass by reference
The difference between your code snippets is only in syntax, where the first syntax is now deprecated.
Passing by reference vs. passing by value
Let's pretend $x
is a piece of paper with 5
written on it.
function sum($y) {
$y = $y + 5;
}
Here $y
is the value of what you have written. You add 5 to such value in your mind, but the note is left untouched.
function sum(&$y) {
$y = $y + 5;
}
With the reference operator (&$y
), you pass the very paper to the function, and it overwrites what's written on it.
For primitive values like numbers, I wouldn't bother and always return
the value you want:
function valuePlusFive($x) {
return $x + 5;
}
$x = 5;
$x = valuePlusFive($x);
Related Topics
Get Numbers from String with PHP
How to Get Insert Id in Mssql in PHP
Trying to Get Laravel 5 Email to Work
How to Re-Save the Entity as Another Row in Doctrine 2
How to Auto Call Function in PHP for Every Other Function Call
PHP - Indirect Modification of Overloaded Property
Trim Unicode Whitespace in PHP 5.2
How to Write a Recursive Regex That Matches Nested Parentheses
Is PHP Str_Word_Count() Multibyte Safe
PHP Simplexml: Insert Node at Certain Position
Too Much Data with Var_Dump in Symfony2 Doctrine2
Laravel Catch Tokenmismatchexception
How to Store an Array in a File to Access as an Array Later with PHP
How to Check If $_Get Is Empty