28
votes

I'm not a PHP programmer (but know other languages), and I'm trying to understand a web page that was done in PHP (5.1.6) in order to do some changes.

The page has the following code (simplified):

$db_hosts = array();
$sql = 'SELECT h.hostid, h.host FROM hosts h ';

$db_items = DBselect($sql);

while($db_item = DBfetch($db_items)){
    $name = $db_item['host'];
    $db_host = &$db_hosts[$db_item['hostid']];
}

I'm trying to understand the last line, $db_host = &$db_hosts[$db_item['hostid']];.

It seems to be creating a new variable, $db_host, and putting something inside it, but I don't understand &$db_hosts.

I'm in doubt because as far as I know, $db_hosts is an empty array.

I found this and this, but I'm not quite sure, because in these links, the operator is "=&", and in the code, the operator is attached to the variable "= &$db_hosts" (it has an space between = and &).

Since I tried to modify it and didn't get success, I thought that it was better to ask for help...

8

8 Answers

36
votes

Those are references, and they are similar to "pointers" in C or C++.

More information is in the PHP manual.

In this case, since $db_hosts is empty, the construct $db_hosts[$db_item['hostid']] will create a new array with an empty item on the index of $db_item['hostid'] and return the item's reference, making $db_host act as an 'alias' for whatever $db_hosts[$db_item['hostid']] is currently.

14
votes

& is used variously in PHP to denote References (see this manual section), but it is misleading to think of it as being an operator in its own right. This is why some people prefer to write $foo =& $bar rather than $foo = &$bar - it means the same thing, but emphasises that the "reference-y-ness" is a property of the assignment, not of the variables.

In some programming languages, such as C or C++, you can "get a reference to" a particular variable; the resulting value can be passed around as a distinct entity, and then "de-referenced" to find out where it points. This is not what PHP references are.

Instead, all PHP variables are actually references to an internal type called a zval. You cannot directly manipulate zvals in PHP, and nor can you make extra layers of indirection - every variable is a reference to a zval, and that's it. (See caveat: objects below.)

What an assignment-by-reference ($foo =& $bar), a pass-by-reference (function foo(&$bar) { ... }), or a return-by-reference (return &$foo) do is tell PHP that you want two variables to point at the same zval. Note that you are not pointing one variable "at" another - they are both equally "real", and calling unset() on either will leave the other completely untouched.

Caveat: objects

It is often misleadingly said that since PHP5 objects are "always passed by reference". The truth is that they have an extra layer of indirection, where the zval is itself a pointer to a particular object. This gives us three different things we can refer to: the variable, the zval it points at, and the object that that points at:

// Create an object, and point three variables at it in different ways:
$foo = new stdClass;
$bar_by_value = $foo;
$bar_by_ref =& $foo;

// Change the object: updates the object shared by all three variables
$foo->value = 42;
// Change the value (zval) of $foo: will update $bar_by_ref, 
//   but $bar_by_value still points at the original object
$foo = 42; 
// Change the variable itself: will never affect $bar_by_value or $bar_by_ref
unset($foo);
12
votes

Question:

What does "&" mean here in PHP?

PHP "&" operator

Makes life more easier once we get used to it..(check example below carefully)

& usually checks bits that are set in both $a and $b are set.

have you even noticed how these calls works?

   error_reporting(E_ERROR | E_WARNING | E_PARSE);
    error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
    error_reporting(E_ALL & ~E_NOTICE);
    error_reporting(E_ALL);

So behind all above is game of bitwise operator and bits.

One usefull case of these is easy configurations like give below, so a single integer field can store thousands of combos for you.

Most people have already read the docs but didn't reliase the real world use case of these bitwise operators.

Example That's can be very useful everyday php life

<?php

class Config {

    // our constants must be 1,2,4,8,16,32,64 ....so on
    const TYPE_CAT=1;
    const TYPE_DOG=2;
    const TYPE_LION=4;
    const TYPE_RAT=8;
    const TYPE_BIRD=16;
    const TYPE_ALL=31;

    private $config;

    public function __construct($config){
        $this->config=$config;

        if($this->is(Config::TYPE_CAT)){
            echo 'cat ';
        }
        if($this->is(Config::TYPE_DOG)){
            echo 'dog ';
        }
        if($this->is(Config::TYPE_RAT)){
            echo 'rat ';
        }
        if($this->is(Config::TYPE_LION)){
            echo 'lion ';
        }
        if($this->is(Config::TYPE_BIRD)){
            echo 'bird ';
        }
        echo "\n";
    }

    private function is($value){
        return $this->config & $value;
    }
}

new Config(Config::TYPE_ALL);
// cat dog rat lion bird
new Config(Config::TYPE_BIRD);
//bird
new Config(Config::TYPE_BIRD | Config::TYPE_DOG);
//dog bird
new Config(Config::TYPE_ALL & ~Config::TYPE_DOG & ~Config::TYPE_CAT);
//rat lion bird
4
votes

Assigning that variable as a reference makes it so that if later on $db_host is changed, the corresponding entry in the $db_hosts array will change as well, and vice versa.

I've seen a fair bit of rather pointless use of references in PHP, cargo cult style. Perhaps this one is needed, perhaps not - you'd have to look at the rest of the program.

3
votes

& is used as a reference. See what references are in http://php.net/manual/en/language.references.php:

References in PHP are a means to access the same variable content by different names. They are not like C pointers; for instance, you cannot perform pointer arithmetic using them, they are not actual memory addresses, and so on.

2
votes

The & is used to get a reference to a variable. It's similar to references in other languages like C++, with some significant differences. See the PHP Manual's section on references.

0
votes

Here is simple example to explain the meaning of PHP & operator:

<?php

$x = "Hello";

$y = &$x;
echo "Value of x : " . $x . "\n";
echo "Value of y : " . $y . "\n";

$y = "Hi"; // Since $y is alias or reference of the variable $x, so value of $x will also be changed, see below:

echo "Value of x : " . $x . "\n";
echo "Value of y : " . $y . "\n";

Output of the above code is as follow:

Value of x : Hello
Value of y : Hello
Value of x : Hi
Value of y : Hi

From the above example, it is clear that it is reference of the variable.

From official documentation: What References Are

References in PHP are a means to access the same variable content by different names. They are not like C pointers; for instance, you cannot perform pointer arithmetic using them, they are not actual memory addresses, and so on. See What References Are Not for more information. 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.