文字

引用返回

引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。不要用返回引用来增加性能,引擎足够聪明来自己进行优化。仅在有合理的技术原因时才返回引用!要返回引用,使用此语法:

<?php
class  foo  {
    public 
$value  42 ;

    public function &
getValue () {
        return 
$this -> value ;
    }
}

$obj  = new  foo ;
$myValue  = & $obj -> getValue ();  // $myValue is a reference to $obj->value, which is 42.
$obj -> value  2 ;
echo 
$myValue ;                 // prints the new value of $obj->value, i.e. 2.
?>
本例中 getValue 函数所返回的对象的属性将被赋值,而不是拷贝,就和没有用引用语法一样。

Note: 和参数传递不同,这里必须在两个地方都用 & 符号——指出返回的是一个引用,而不是通常的一个拷贝,同样也指出 $myValue 是作为引用的绑定,而不是通常的赋值。

Note: 如果试图这样从函数返回引用:return ($this->value);,这将不会起作用,因为在试图返回一个表达式的结果而不是一个引用的变量。只能从函数返回引用变量——没别的方法。如果代码试图返回一个动态表达式或 new 运算符的结果,自 PHP 4.4.0 和 PHP 5.1.0 起会发出一条 E_NOTICE 错误。

用户评论:

[#1] Karim dot Khaled dot Wahby at outlook dot com [2015-04-17 21:32:50]

You can also return a function like this :
<?php
            
function ReturnFunc ($num$num1)
            {
                if (
$num == 1)
                {
                    
// use is to inheret the variable $num1 from the calling function 
                    // You can also Use global to refrance to global vars ;
                    
return function ($num2) use ($num1){return $num1+$num2;} ;
                }
                else if (
$num == 2)
                {
                    return function (
$num2) use ($num1){return $num1-$num2;} ; 
                }
            }
            
            function 
InvokeTheReturnedFunc($num,$num1$num2)
            {
                
$func ReturnFunc($num$num1) ;
                echo 
gettype($func) . '<br />'// Object
                
return $func($num2) ;
            }
            echo 
InvokeTheReturnedFunc(158) . '<br />'// 13
            
echo InvokeTheReturnedFunc(258) . '<br />'// -3
            
echo $asdasd // would generate a notice
   
?>

[#2] civilization28 at gmail dot com [2014-09-17 01:49:59]

Zayfod's example above is useful, but I feel that it needs more explanation. The point that should be made is that a parameter passed in by reference can be changed to reference something else, resulting in later changes to the local variable not affecting the passed in variable:

<?php

function    & func_b ()
{
    
$some_var 2;
    return 
$some_var;
}

function    
func_a (& $param)
{
    
# $param is 1 here
    
$param = & func_b();    # Here the reference is changed and
                                           # the "&" in "func_a (& $param)"
                                           # is no longer in effect at all.
    # $param is 2 here
    
$param++;    # Has no effect on $var.
}

$var 1;
func_a($var);
# $var is still 1 here!!!    Because the reference was changed.

?>

[#3] Anonymous [2014-03-05 04:18:13]

I learned a painful lesson working with a class method that would pass by reference.   

In short, if you have a method in a class that is initialed with ampersand during declaration, do not use another ampersand when using the method as in &$this->method();

For example
<?php
class {
    public function &
hello(){
        static 
$a='';
        return 
$a;
    }
    public function 
bello(){
        
$b=&$this->hello();  // incorrect. Do not use ampersand.
        
$b=$this->hello();  // $b is a reference  to the static variable.
}
?>

[#4] benjamin dot delespierre at gmail dot com [2011-02-23 05:36:32]

Keep in mind that returning by reference doesn't work with __callStatic:

<?php
class Test {
  private static 
$_inst;
  public static function & 
__callStatic ($name$args) {
    if (!isset(static::
$_inst)){ 
      echo 
"create";
      static::
$_inst = (object)"test";
   }
   return static::
$_inst;
}

var_dump($a = &Test::abc()); // prints 'create'
$a null;
var_dump(Test::abc()); // doesn't prints and the instance still exists in Test::$_inst
?>

[#5] szymoncofalik at gmail dot com [2011-01-28 12:41:51]

Sometimes, you would like to return NULL with a function returning reference, to indicate the end of chain of elements. However this generates E_NOTICE. Here is little tip, how to prevent that:

<?php
class Foo {
   const 
$nullGuard NULL;
   
// ... some declarations and definitions
   
public function &next() {
      
// ...
      
if (!$end) return $bar;
      else return 
$this->nullGuard;
   }
}
?>


by doing this you can do smth like this without notices:

<?php
$f 
= new Foo();
// ...
while (($item $f->next()) != NULL) {
// ...
}
?>


you may also use global variable:
global $nullGuard;
return $nullGuard;

[#6] spidgorny at gmail dot com [2010-03-19 06:18:05]

When returning reference to the object member which is instantiated inside the function, the object is destructed upon returning (which is a problem). It's easier to see the code:

<?php

class MemcacheArray {
    public 
$data;

    ...

    

    
function &getData($file$expire 3600) {
        
$o = new MemcacheArray($file$expire);
        return 
$o->data;
    }
?>


Here, destructor is called upon return() and the reference becomes a normal variable.

My solution is to store objects in a pool until the final exit(), but I don't like it. Any other ideas?

<?php
    
protected static $instances = array();

    function &
getData($file$expire 3600) {
        
$o = new MemcacheArray($file$expire);
        
self::$instances[$file] = $o// keep object from destructing too early
        
return $o->data;
    }
?>

[#7] sandaimespaceman at gmail dot com [2008-11-02 08:52:31]

The &b() function returns a reference of $a in the global scope.

<?php
$a 
0;
function &
b()
{
    global 
$a;
    return 
$a;
}
$c = &b();
$c++;
echo
"
\$a: 
$a
\$b: 
$c
"
?>


It outputs:

$a: 1 $b: 1

[#8] Spad-XIII [2008-01-31 05:01:15]

a little addition to the example of pixel at minikomp dot com here below
<?php

    
function &func(){
        static 
$static 0;
        
$static++;
        return 
$static;
    }

    
$var1 =& func();
    echo 
"var1:"$var1// 1
    
func();
    
func();
    echo 
"var1:"$var1// 3
    
$var2 func(); // assignment without the &
    
echo "var2:"$var2// 4
    
func();
    
func();
    echo 
"var1:"$var1// 6
    
echo "var2:"$var2// still 4

?>

[#9] pixel at minikomp dot com [2007-12-30 16:21:00]

<?php

    
function &func(){
        static 
$static 0;
        
$static++;
        return 
$static;
    }

    
$var =& func();
    echo 
$var// 1
    
func();
    
func();
    
func();
    
func();
    echo 
$var// 5

?>

[#10] stanlemon at mac dot com [2007-09-28 10:51:42]

I haven't seen anyone note method chaining in PHP5.  When an object is returned by a method in PHP5 it is returned by default as a reference, and the new Zend Engine 2 allows you to chain method calls from those returned objects.  For example consider this code:

<?php

class Foo {

    protected 
$bar;

    public function 
__construct() {
        
$this->bar = new Bar();

        print 
"Foo\n";
    }    
    
    public function 
getBar() {
        return 
$this->bar;
    }
}

class 
Bar {

    public function 
__construct() {
        print 
"Bar\n";
    }
    
    public function 
helloWorld() {
        print 
"Hello World\n";
    }
}

function 
test() {
    return new 
Foo();
}

test()->getBar()->helloWorld();

?>


Notice how we called test() which was not on an object, but returned an instance of Foo, followed by a method on Foo, getBar() which returned an instance of Bar and finally called one of its methods helloWorld().  Those familiar with other interpretive languages (Java to name one) will recognize this functionality.  For whatever reason this change doesn't seem to be documented very well, so hopefully someone will find this helpful.

[#11] php at thunder-2000 dot com [2007-02-02 02:31:32]

If you want to get a part of an array to manipulate, you can use this function

function &getArrayField(&$array,$path) {
  if (!empty($path)) {
    if (empty($array[$path[0]])) return NULL;
    else return getArrayField($array[$path[0]], array_slice($path, 1));
  } else {
    return $array;
  }
}

Use it like this:

$partArray =& getArrayField($GLOBALS,array("config","modul1"));

You can manipulate $partArray and the changes are also made with $GLOBALS.

[#12] rwruck [2006-02-27 09:22:16]

The note about using parentheses when returning references is only true if the variable you try to return does not already contain a reference.

<?php
// Will return a reference
function& getref1()
  {
  
$ref =& $GLOBALS['somevar'];
  return (
$ref);
  }

// Will return a value (and emit a notice)
function& getref2()
  {
  
$ref 42;
  return (
$ref);
  }

// Will return a reference
function& getref3()
  {
  static 
$ref 42;
  return (
$ref);
  }
?>

[#13] willem at designhulp dot nl [2005-10-09 04:54:40]

There is an important difference between php5 and php4 with references.

Lets say you have a class with a method called 'get_instance' to get a reference to an exsisting class and it's properties.

<?php
class mysql {
    function 
get_instance(){
        
// check if object exsists
        
if(empty($_ENV['instances']['mysql'])){
            
// no object yet, create an object
            
$_ENV['instances']['mysql'] = new mysql;
        }
        
// return reference to object
        
$ref = &$_ENV['instances']['mysql'];
        return 
$ref;
    }
}
?>


Now to get the exsisting object you can use
mysql::get_instance();

Though this works in php4 and in php5, but in php4 all data will be lost as if it is a new object while in php5 all properties in the object remain.

[#14] obscvresovl at NOSPAM dot hotmail dot com [2004-12-24 13:09:31]

An example of returning references:

<?php

$var 
1;
$num NULL;

function &
blah()
{
    
$var =& $GLOBALS["var"]; # the same as global $var;
    
$var++;
    return 
$var;
}

$num = &blah();

echo 
$num# 2

blah();

echo 
$num# 3

?>


Note: if you take the & off from the function, the second echo will be 2, because without & the var $num contains its returning value and not its returning reference.

[#15] hawcue at yahoo dot com [2004-03-16 19:58:02]

Be careful when using tinary operation condition?value1:value2

See the following code:

$a=1;
function &foo()
{
  global $a;
  return isset($a)?$a:null;
}
$b=&foo();
echo $b;   // shows 1
$b=2;
echo $a;   // shows 1 (not 2! because $b got a copy of $a)

To let $b be a reference to $a, use "if..then.." in the function.

[#16] contact at infopol dot fr [2004-02-12 09:36:28]

A note about returning references embedded in non-reference arrays :

<?php
$foo
;

function 
bar () {
    global 
$foo;
    
$return = array();
    
$return[] =& $foo;
    return 
$return;
}

$foo 1;
$foobar bar();
$foobar[0] = 2;
echo 
$foo;
?>


results in "2" because the reference is copied (pretty neat).

[#17] zayfod at yahoo dot com [2003-12-03 09:23:03]

There is a small exception to the note on this page of the documentation. You do not have to use & to indicate that reference binding should be done when you assign to a value passed by reference the result of a function which returns by reference.

Consider the following two exaples:

<?php

function    & func_b ()
{
    
$some_var 2;
    return 
$some_var;
}

function    
func_a (& $param)
{
    
# $param is 1 here
    
$param = & func_b();
    
# $param is 2 here
}

$var 1;
func_a($var);
# $var is still 1 here!!!

?>


The second example works as intended:

<?php

function    & func_b ()
{
    
$some_var 2;
    return 
$some_var;
}

function    
func_a (& $param)
{
    
# $param is 1 here
    
$param func_b();
    
# $param is 2 here
}

$var 1;
func_a($var);
# $var is 2 here as intended

?>


(Experienced with PHP 4.3.0)

上一篇: 下一篇: