PHP.mk документација

Што прават референците

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

language.references.whatdo.php PHP.net прокси Преводот е вчитан
Оригинал на PHP.net
Патека language.references.whatdo.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + преведен приказ Кодовите, табелите и белешките остануваат читливи во истиот тек.
Што прават референците

Референца за `language.references.whatdo.php` со подобрена типографија и навигација.

language.references.whatdo.php

Што прават референците

Постојат три основни операции што се изведуваат со користење на референци: доделување по референца, проследување по референцаПрепорачаниот начин за избегнување на SQL инјекција е со врзување на сите податоци преку подготвени изрази. Користењето на параметризирани прашања не е доволно за целосно избегнување на SQL инјекција, но тоа е најлесниот и најбезбедниот начин за обезбедување влез во SQL изразите. Сите динамични литерали на податоци во враќање по референца. Овој дел ќе даде вовед во овие операции, со линкови за понатамошно читање.

Доделување по референца

Во првата од нив, PHP референците ви дозволуваат две променливи да упатуваат на иста содржина. Значи, кога правите:

<?php

$a
=& $b;

?>
тоа значи дека $a and $b укажуваат на иста содржина.

Забелешка:

$a and $b се целосно еднакви овде. $a не упатува на $b или обратно. $a and $b укажуваат на исто место.

Забелешка:

Ако доделите, проследите или вратите недефинирана променлива по референца, таа ќе биде креирана.

Пример #1 Користење референци со недефинирани променливи

<?php

function foo(&$var) {}

foo($a); // $a is "created" and assigned to null

$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)

$c = new stdClass();
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)

?>

Истата синтакса може да се користи со функции што враќаат референци:

<?php

$foo
=& find_var($bar);

?>

Користењето на истата синтакса со функција што прави not враќање по референца ќе даде грешка, исто како и користењето со резултатот од new операторот. Иако објектите се проследуваат како покажувачи, тие не се исти како референците, како што е објаснето под Објекти и референци.

Ги ескејпува специјалните знаци во стринг за употреба во SQL изјава

Ако доделите референца на променлива што е декларирана global внатре во функција, референцата ќе биде видлива само внатре во функцијата. Можете да го избегнете ова со користење на $GLOBALS array.

внатре во функција, референцата ќе биде видлива само внатре во функцијата. Можете да го избегнете ова со користење на

<?php

$var1
= "Example variable";
$var2 = "";

function
global_references($use_globals)
{
global
$var1, $var2;

if (!
$use_globals) {
$var2 =& $var1; // visible only inside the function
} else {
$GLOBALS["var2"] =& $var1; // visible also in global context
}
}

global_references(false);
echo
"var2 is set to '$var2'\n"; // var2 is set to ''

global_references(true);
echo
"var2 is set to '$var2'\n"; // var2 is set to 'Example variable'

?>
Пример #2 Референцирање на глобални променливи внатре во функции global $var; Размислете за $var =& $GLOBALS['var'];како кратенка за $var . Така доделувањето на друга референца на

Забелешка:

ја менува само референцата на локалната променлива. foreach Ако доделите вредност на променлива со референци во

израз, референците исто така се менуваат.

<?php

$ref
= 0;
$row =& $ref;

foreach (array(
1, 2, 3) as $row) {
// Do something
}

echo
$ref; // 3 - last element of the iterated array

?>

Пример #3 Референци и foreach израз array() Иако не е строго доделување по референца, изразите создадени со јазичниот конструкт & исто така може да се однесуваат како такви со додавање на префикс

<?php

$a
= 1;
$b = array(2, 3);

$arr = array(&$a, &$b[0], &$b[1]);
$arr[0]++;
$arr[1]++;
$arr[2]++;
/* $a == 2, $b == array(3, 4); */

?>

на елементот од низата за додавање. Пример:

<?php

/* Assignment of scalar variables */
$a = 1;
$b =& $a;
$c = $b;
$c = 7; // $c is not a reference; no change to $a or $b

/* Assignment of array variables */
$arr = array(1);
$a =& $arr[0]; // $a and $arr[0] are in the same reference set
$arr2 = $arr; // Not an assignment-by-reference!
$arr2[0]++;
/* $a == 2, $arr == array(2) */
/* The contents of $arr are changed even though it's not a reference! */

?>
Сепак, имајте на ум дека референците внатре во низите се потенцијално опасни. Нормалното доделување (не по референца) со референца на десната страна не ја претвора левата страна во референца, но референците внатре во низите се зачувуваат во овие нормални доделувања. Ова се однесува и на повици на функции каде низата се поминува по вредност. Пример:

Со други зборови, референтното однесување на низите се дефинира на основа елемент по елемент; референтното однесување на индивидуалните елементи е одвоено од референтниот статус на контејнерот на низата.

Поминување по референца

<?php

function foo(&$var)
{
$var++;
}

$a=5;
foo($a);

?>
Втората работа што ја прават референците е поминување на променливи по референца. Ова се прави со создавање локална променлива во функција и променлива во повикувачкиот опсег што реферираат на иста содржина. Пример: $a ќе направи foo да биде 6. Ова се случува затоа што во функцијата $var променливата $aвнатре во функција, референцата ќе биде видлива само внатре во функцијата. Можете да го избегнете ова со користење на проследување по референца section.

. За повеќе информации за ова, прочитајте го

Враќање по референца Третата работа што можат да ја прават референциите е.

Белешки од корисници фајлови со горенаведените екстензии. Иако е форма на безбедност преку замаглување, тоа е мала превентивна мерка со малку недостатоци.

враќање по референца
20 години пред
I ran into something when using an expanded version of the example of pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu below.
This could be somewhat confusing although it is perfectly clear if you have read the manual carfully. It makes the fact that references always point to the content of a variable perfectly clear (at least to me).

<?php
$a = 1;
$c = 2;
$b =& $a; // $b points to 1
$a =& $c; // $a points now to 2, but $b still to 1;
echo $a, " ", $b;
// Output: 2 1
?>
ladoo at gmx dot at
пред 18 години
Watch out for this:

foreach ($somearray as &$i) {
  // update some $i...
}
...
foreach ($somearray as $i) {
  // last element of $somearray is mysteriously overwritten!
}

Problem is $i contians reference to last element of $somearray after the first foreach, and the second foreach happily assigns to it!
Hlavac
пред 15 години
It appears that references can have side-effects.  Below are two examples.  Both are simply copying one array to another.  In the second example, a reference is made to a value in the first array before the copy.  In the first example the value at index 0 points to two separate memory locations. In the second example, the value at index 0 points to the same memory location. 

I won't say this is a bug, because I don't know what the designed behavior of PHP is, but I don't think ANY developers would expect this behavior, so look out.

An example of where this could cause problems is if you do an array copy in a script and expect on type of behavior, but then later add a reference to a value in the array earlier in the script, and then find that the array copy behavior has unexpectedly changed.

<?php
// Example one
$arr1 = array(1);
echo "\nbefore:\n";
echo "\$arr1[0] == {$arr1[0]}\n";
$arr2 = $arr1;
$arr2[0]++;
echo "\nafter:\n";
echo "\$arr1[0] == {$arr1[0]}\n";
echo "\$arr2[0] == {$arr2[0]}\n";

// Example two
$arr3 = array(1);
$a =& $arr3[0];
echo "\nbefore:\n";
echo "\$a == $a\n";
echo "\$arr3[0] == {$arr3[0]}\n";
$arr4 = $arr3;
$arr4[0]++;
echo "\nafter:\n";
echo "\$a == $a\n";
echo "\$arr3[0] == {$arr3[0]}\n";
echo "\$arr4[0] == {$arr4[0]}\n";
?>
elrah [] polyptych [dot] com
пред 18 години
Something that might not be obvious on the first look:
If you want to cycle through an array with references, you must not use a simple value assigning foreach control structure. You have to use an extended key-value assigning foreach or a for control structure.

A simple value assigning foreach control structure produces a copy of an object or value. The following code

$v1=0;
$arrV=array(&$v1,&$v1);
foreach ($arrV as $v)
{
  $v1++;
  echo $v."\n";
}

yields

0
1

which means $v in foreach is not a reference to $v1 but a copy of the object the actual element in the array was referencing to.

The codes

$v1=0;
$arrV=array(&$v1,&$v1);
foreach ($arrV as $k=>$v)
{
    $v1++;
    echo $arrV[$k]."\n";
}

and

$v1=0;
$arrV=array(&$v1,&$v1);
$c=count($arrV);
for ($i=0; $i<$c;$i++)
{
    $v1++;
    echo $arrV[$i]."\n";
}

both yield

1
2

and therefor cycle through the original objects (both $v1), which is, in terms of our aim, what we have been looking for.

(tested with php 4.1.3)
amp at gmx dot info
пред 14 години
in PHP you don't really need pointer anymore if you want to share an  object across your program

<?php
class foo{
        protected $name;
        function __construct($str){
                $this->name = $str;
        }
        function __toString(){
                return  'my name is "'. $this->name .'" and I live in "' . __CLASS__ . '".' . "\n";
        }
        function setName($str){
                $this->name = $str;
        }
}

class MasterOne{
        protected $foo;
        function __construct($f){
                $this->foo = $f;
        }
        function __toString(){
                return 'Master: ' . __CLASS__ . ' | foo: ' . $this->foo . "\n";
        }
        function setFooName($str){
                $this->foo->setName( $str );
        }
}

class MasterTwo{
        protected $foo;
        function __construct($f){
                $this->foo = $f;
        }
        function __toString(){
                return 'Master: ' . __CLASS__ . ' | foo: ' . $this->foo . "\n";
        }
        function setFooName($str){
                $this->foo->setName( $str );
        }
}

$bar = new foo('bar');

print("\n");
print("Only Created \$bar and printing \$bar\n");
print( $bar );

print("\n");
print("Now \$baz is referenced to \$bar and printing \$bar and \$baz\n");
$baz =& $bar;
print( $bar );

print("\n");
print("Now Creating MasterOne and Two and passing \$bar to both constructors\n");
$m1 = new MasterOne( $bar );
$m2 = new MasterTwo( $bar );
print( $m1 );
print( $m2 );

print("\n");
print("Now changing value of \$bar and printing \$bar and \$baz\n");
$bar->setName('baz');
print( $bar );
print( $baz );

print("\n");
print("Now printing again MasterOne and Two\n");
print( $m1 );
print( $m2 );

print("\n");
print("Now changing MasterTwo's foo name and printing again MasterOne and Two\n");
$m2->setFooName( 'MasterTwo\'s Foo' );
print( $m1 );
print( $m2 );

print("Also printing \$bar and \$baz\n");
print( $bar );
print( $baz );
?>
nay at woodcraftsrus dot com
пред 4 години
It matters if you are playing with a reference or with a value

Here we are working with values so working on a reference updates original variable too;

$a = 1;
$c = 22;

$b = & $a;
echo "$a, $b"; //Output: 1, 1

$b++;
echo "$a, $b";//Output: 2, 2 both values are updated

$b = 10;
echo "$a, $b";//Output: 10, 10 both values are updated

$b =$c; //This assigns value 2 to $b which also updates $a
echo "$a, $b";//Output: 22, 22

But, if instead of $b=$c you do
$b = &$c; //Only value of $b is updated, $a still points to 10, $b serves now reference to variable $c

echo "$a, $b"//Output: 10, 22
dexant9t at gmail dot com
пред 16 години
I think a correction to my last post is in order.

When there is a constructor, the strange behavior mentioned in my last post doesn't occur. My guess is that php was treating reftest() as a constructor (maybe because it was the first function?) and running it upon instantiation.

<?php
class reftest
{
    public $a = 1;
    public $c = 1;

    public function __construct()
    {
        return 0;
    }

    public function reftest()
    {
        $b =& $this->a;
        $b++;
    }

    public function reftest2()
    {
        $d =& $this->c;
        $d++;
    }
}

$reference = new reftest();

$reference->reftest();
$reference->reftest2();

echo $reference->a; //Echoes 2.
echo $reference->c; //Echoes 2.
?>
Анонимен
пред 10 години
to reply to ' elrah [] polyptych [dot] com ', one thing to keep in mind is that array (or similar large data holders) are by default passed by reference. So the behaviour is not side effect. And for array copy and passing array inside function  always done by 'pass by reference'...
Amaroq
21 години пред
In reply to lars at riisgaardribe dot dk, 

When a variable is copied, a reference is used internally until the copy is modified.  Therefore you shouldn't use references at all in your situation as it doesn't save any memory usage and increases the chance of logic bugs, as you discoved.
php.devel at homelinkcs dot com
пред 18 години
Solution to post "php at hood dot id dot au 04-Mar-2007 10:56":

<?php
$a1 = array('a'=>'a');
$a2 = array('a'=>'b');

foreach ($a1 as $k=>&$v)
$v = 'x';

echo $a1['a']; // will echo x

unset($GLOBALS['v']);

foreach ($a2 as $k=>$v)
{}

echo $a1['a']; // will echo x

?>
dovbysh at gmail dot com
пред 18 години
points to post below me. 
When you're doing the references with loops, you need to unset($var). 

for example 
<?php 
foreach($var as &$value)
{
...
}
unset($value);
?>
dnhuff на acm dot org
пред 17 години
In reply to Drewseph using foo($a = 'set'); where $a is a reference formal parameter.

$a = 'set' is an expression. Expressions cannot be passed by reference, don't you just hate that, I do. If you turn on error reporting for E_NOTICE, you will be told about it.

Resolution: $a = 'set'; foo($a); this does what you want.
charles at org oo dot com
пред 17 години
If you set a variable before passing it to a function that takes a variable as a reference, it is much harder (if not impossible) to edit the variable within the function.

Example:
<?php
function foo(&$bar) {
    $bar = "hello\n";
}

foo($unset);
echo($unset);
foo($set = "set\n");
echo($set);

?>

Output:
hello
set

It baffles me, but there you have it.
Drewseph
пред 15 години
In this example class name is different from its first function and however there is no construction function. In the end as you guess "a" and "c" are equal. So if there is no construction function at same time class and its first function names are the same, "a" and "c" doesn't equal forever. In my opinion php doesn't seek any function for the construction as long as their names differ from each others.

<?php
class reftest_new
{
    public $a = 1;
    public $c = 1;

    public function reftest()
    {
        $b =& $this->a;
        $b++;
    }

    public function reftest2()
    {
        $d =& $this->c;
        $d++;
    }
}

$reference = new reftest_new();

$reference->reftest();
$reference->reftest2();

echo $reference->a; //Echoes 2.
echo $reference->c; //Echoes 2.
?>
akinaslan at gmail dot com
19 години пред
I discovered something today using references in a foreach

<?php
$a1 = array('a'=>'a');
$a2 = array('a'=>'b');

foreach ($a1 as $k=>&$v)
$v = 'x';

echo $a1['a']; // will echo x

foreach ($a2 as $k=>$v)
{}

echo $a1['a']; // will echo b (!)
?>

After reading the manual this looks like it is meant to happen. But it confused me for a few days!

(The solution I used was to turn the second foreach into a reference too)
php at hood dot id dot au
пред 18 години
Here's a good little example of referencing. It was the best way for me to understand, hopefully it can help others.

$b = 2;
$a =& $b;
$c = $a;
echo $c;

// Then... $c = 2
dexant9t at gmail dot com
пред 17 години
The order in which you reference your variables matters.

<?php
$a1 = "One";
$a2 = "Two";
$b1 = "Three";
$b2 = "Four";

$b1 =& $a1;
$a2 =& $b2;

echo $a1; //Echoes "One"
echo $b1; //Echoes "One"

echo $a2; //Echoes "Four"
echo $b2; //Echoes "Four"
?>
Одант
12 години пред
About the example on array references.
I think this should be written in the array chapter as well.
Indeed if you are new to programming language in some way, you should beware that arrays are pointers to a vector of Byte(s).

<?php $arr = array(1); ?>
$arr here contains a reference to which the array is located.
Writing :
<?php echo $arr[0]; ?>
dereferences the array to access its very first element.

Now something that you should also be aware of  (even you are not new to programming languages) is that PHP use references to contains the different values of an array. And that makes sense because the type of the elements of a PHP array can be different.

Consider the following example :

<?php

$arr = array(1, 'test');

$point_to_test =& $arr[1];

$new_ref = 'new';

$arr[1] =& $new_ref;

echo $arr[1]; // echo 'new';
echo $point_to_test; // echo 'test' ! (still pointed somewhere in the memory)

?>
dexant9t at gmail dot com
пред 16 години
When using references in a class, you can reference $this-> variables.

<?php
class reftest
{
    public $a = 1;
    public $c = 1;

    public function reftest()
    {
        $b =& $this->a;
        $b = 2;
    }

    public function reftest2()
    {
        $d =& $this->c;
        $d++;
    }
}

$reference = new reftest();

$reference->reftest();
$reference->reftest2();

echo $reference->a; //Echoes 2.
echo $reference->c; //Echoes 2.
?>

However, this doesn't appear to be completely trustworthy. In some cases, it can act strangely.

<?php
class reftest
{
    public $a = 1;
    public $c = 1;

    public function reftest()
    {
        $b =& $this->a;
        $b++;
    }

    public function reftest2()
    {
        $d =& $this->c;
        $d++;
    }
}

$reference = new reftest();

$reference->reftest();
$reference->reftest2();

echo $reference->a; //Echoes 3.
echo $reference->c; //Echoes 2.
?>

In this second code block, I've changed reftest() so that $b increments instead of just gets changed to 2. Somehow, it winds up equaling 3 instead of 2 as it should.
akashwebdev at gmail dot com
пред 16 години
An interesting if offbeat use for references:  Creating an array with an arbitrary number of dimensions.

For example, a function that takes the result set from a database and produces a multidimensional array keyed according to one (or more) columns, which might be useful if you want your result set to be accessible in a hierarchial manner, or even if you just want your results keyed by the values of each row's primary/unique key fields.

<?php
function array_key_by($data, $keys, $dupl = false)
/* 
 * $data  - Multidimensional array to be keyed
 * $keys  - List containing the index/key(s) to use.
 * $dupl  - How to handle rows containing the same values.  TRUE stores it as an Array, FALSE overwrites the previous row.
 *          
 * Returns a multidimensional array indexed by $keys, or NULL if error.
 * The number of dimensions is equal to the number of $keys provided (+1 if $dupl=TRUE).
 */   
{
    // Sanity check
    if (!is_array($data)) return null;
    
    // Allow passing single key as a scalar
    if (is_string($keys) or is_integer($keys)) $keys = Array($keys);
    elseif (!is_array($keys)) return null;

    // Our output array
    $out = Array();
    
    // Loop through each row of our input $data
    foreach($data as $cx => $row) if (is_array($row))
    {
      
      // Loop through our $keys
      foreach($keys as $key)
      {
        $value = $row[$key];

        if (!isset($last)) // First $key only
        {
          if (!isset($out[$value])) $out[$value] = Array();
          $last =& $out; // Bind $last to $out
        }
        else // Second and subsequent $key....
        {
          if (!isset($last[$value])) $last[$value] = Array();
        }

        // Bind $last to one dimension 'deeper'.
        // First lap: was &$out, now &$out[...]
        // Second lap: was &$out[...], now &$out[...][...]
        // Third lap:  was &$out[...][...], now &$out[...][...][...]
        // (etc.)
        $last =& $last[$value];
      }
      
      if (isset($last))
      {
        // At this point, copy the $row into our output array
        if ($dupl) $last[$cx] = $row; // Keep previous
        else       $last = $row; // Overwrite previous
      }
      unset($last); // Break the reference
    }
    else return NULL;
    
    // Done
    return $out;
}

// A sample result set to test the function with
$data = Array(Array('name' => 'row 1', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_a'),
              Array('name' => 'row 2', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_b'),
              Array('name' => 'row 3', 'foo' => 'foo_a', 'bar' => 'bar_b', 'baz' => 'baz_c'),
              Array('name' => 'row 4', 'foo' => 'foo_b', 'bar' => 'bar_c', 'baz' => 'baz_d')
              ); 

// First, let's key it by one column (result: two-dimensional array)
print_r(array_key_by($data, 'baz'));

// Or, key it by two columns (result: 3-dimensional array)
print_r(array_key_by($data, Array('baz', 'bar')));

// We could also key it by three columns (result: 4-dimensional array)
print_r(array_key_by($data, Array('baz', 'bar', 'foo')));

?>
firespade at gmail dot com
пред 13 години
This appears to be the hidden behavior: When a class function has the same name as the class, it seems to be implicitly called when an object of the class is created.
For instance, you may take a look at the naming of the function "reftest()": it is in the class "reftest". The behavior can be tested as follows:

<?php
class reftest
{
    public $a = 1;
    public $c = 1;

    public function reftest1()
    {
        $b =& $this->a;
        $b++;
    }

    public function reftest2()
    {
        $d =& $this->c;
        $d++;
    }
    
    public function reftest()
    {
       echo "REFTEST() called here!\n";
    }
}

$reference = new reftest();
/*You must notice the above will also implicitly call reference->reftest()*/

$reference->reftest1();
$reference->reftest2();

echo $reference->a."\n"; //Echoes 2, not 3 as previously noticed.
echo $reference->c."\n"; //Echoes 2.
?>

The above outputs:

REFTEST() called here!
2
2

Notice that reftest() appears to be called (though no explicit call to it was made)!
joakim na lous dot org
пред 22 години
So to make a by-reference setter function, you need to specify reference semantics _both_ in the parameter list _and_ the assignment, like this:

class foo{
   var $bar;
   function setBar(&$newBar){
      $this->bar =& newBar;
   }
}

Forget any of the two '&'s, and $foo->bar will end up being a copy after the call to setBar.
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.