2008-08-03 70 views

Trả lời

207

Đó là bởi giá trị theo PHP Documentation.

Theo mặc định, đối số hàm được chuyển theo giá trị (để nếu giá trị của đối số trong hàm bị thay đổi, nó không được thay đổi bên ngoài hàm). Để cho phép một hàm sửa đổi các đối số của nó, chúng phải được chuyển qua tham chiếu.

Để có đối số cho hàm luôn được chuyển bằng tham chiếu, hãy thêm một ký hiệu (&) vào tên đối số trong định nghĩa hàm.

<?php 
function add_some_extra(&$string) 
{ 
    $string .= 'and something extra.'; 
} 

$str = 'This is a string, '; 
add_some_extra($str); 
echo $str; // outputs 'This is a string, and something extra.' 
?> 
+4

Tôi cũng đã có nghi ngờ này (newbie) - vì vậy chỉ để được rõ ràng, điều này sẽ giống như '$ str = add_some_extra ($ str);' nếu tôi không sử dụng tài liệu tham khảo, phải không? thì giá trị gia tăng thực sự của điều đó là gì? –

+3

@Obmerk Nếu bạn _not_ sử dụng dấu và để biểu thị bằng tham chiếu, nó sẽ không tương đương. Lưu ý cách hàm không có câu lệnh trả về, vì vậy '$ str' sẽ được gán null, trong trường hợp của bạn. –

+0

nếu bạn làm theo cách này @ObmerkKronen thì bạn sẽ phải trả lại giá trị và cũng bắt được nó thông qua mã của bạn. Biến ban đầu sẽ vẫn giữ nguyên. –

-6

Phụ thuộc vào phiên bản, 4 là theo giá trị, 5 là tham chiếu.

+8

Tôi không nghĩ điều này là đúng. –

17

Biến PHP được gán theo giá trị, được chuyển đến hàm theo giá trị và khi chứa/đại diện đối tượng được chuyển theo tham chiếu. Bạn có thể buộc các biến để vượt qua bằng cách tham khảo cách sử dụng một &

giao theo giá trị/tài liệu tham khảo ví dụ:

$var1 = "test"; 
$var2 = $var1; 
$var2 = "new test"; 
$var3 = &$var2; 
$var3 = "final test"; 

print ("var1: $var1, var2: $var2, var3: $var3); 

sẽ ra

var1: kiểm tra, var2: kiểm tra cuối cùng, var3: kiểm tra chính thức

Được chuyển bởi giá trị/tham chiếu exampe:

$var1 = "foo"; 
$var2 = "bar"; 

changeThem($var1, $var2); 

print "var1: $var1, var2: $var2"; 

function changeThem($var1, &$var2){ 
    $var1 = "FOO"; 
    $var2 = "BAR"; 
} 

sẽ ra:

var1: foo, var2 BAR

biến Object thông qua tham khảo exampe:

class Foo{ 
    public $var1; 

    function __construct(){ 
     $this->var1 = "foo"; 
    } 

    public function printFoo(){ 
     print $this->var1; 
    } 
} 


$foo = new Foo(); 

changeFoo($foo); 

$foo->printFoo(); 

function changeFoo($foo){ 
    $foo->var1 = "FOO"; 
} 

Would đầu ra:

FOO

(mà ví dụ cuối cùng có thể là tốt hơn có lẽ ...)

+0

"Đối tượng" không phải là giá trị trong PHP5 và không thể "được chuyển". Giá trị của '$ foo' là một con trỏ * đến một đối tượng *. '$ foo' được truyền bởi giá trị ** tới hàm' changeFoo() ', vì' changeFoo() 'không khai báo tham số của nó bằng' & '. – newacct

23

http://www.php.net/manual/en/migration5.oop.php

Trong PHP 5 có một Object Model mới. Việc xử lý các đối tượng của PHP đã được viết lại hoàn toàn, cho phép hiệu năng tốt hơn và nhiều tính năng hơn. Trong các phiên bản trước của PHP, các đối tượng được xử lý như các kiểu nguyên thủy (ví dụ các số nguyên và chuỗi). Hạn chế của phương thức này là ngữ nghĩa toàn bộ đối tượng đã được sao chép khi một biến được gán, hoặc được truyền như một tham số cho một phương thức. Trong phương pháp tiếp cận mới, các đối tượng được tham chiếu bằng cách xử lý, chứ không phải theo giá trị (người ta có thể nghĩ về một xử lý như một định danh của đối tượng).

4

Các biến chứa kiểu nguyên thủy được chuyển theo giá trị trong PHP5. Các biến chứa đối tượng được truyền bằng tham chiếu. Có khá một bài viết thú vị từ Linux Journal từ năm 2006 mà đề cập đến điều này và sự khác biệt OO khác giữa 4 và 5.

http://www.linuxjournal.com/article/9170

+0

Tất cả các biến được chuyển bởi giá trị trong PHP nếu tham số của hàm không có '&'. – newacct

51

Có vẻ như rất nhiều người dân bị lẫn lộn bởi các đối tượng cách được truyền cho các chức năng và những gì vượt qua bằng phương tiện tham chiếu. Các biến đối tượng vẫn được truyền theo giá trị, chỉ giá trị của nó được chuyển trong PHP5 là một xử lý tham chiếu. Làm bằng chứng:

<?php 
class Holder { 
    private $value; 

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

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

function swap($x, $y) { 
    $tmp = $x; 
    $x = $y; 
    $y = $tmp; 
} 

$a = new Holder('a'); 
$b = new Holder('b'); 
swap($a, $b); 

echo $a->getValue() . ", " . $b->getValue() . "\n"; 

Đầu ra:

a, b 

Để pass by reference nghĩa là chúng ta có thể sửa đổi các biến được nhìn thấy bởi người gọi. Mà rõ ràng các mã trên không làm. Chúng ta cần phải thay đổi các chức năng trao đổi để:

<?php 
function swap(&$x, &$y) { 
    $tmp = $x; 
    $x = $y; 
    $y = $tmp; 
} 

$a = new Holder('a'); 
$b = new Holder('b'); 
swap($a, $b); 

echo $a->getValue() . ", " . $b->getValue() . "\n"; 

Đầu ra:

b, a 

để vượt qua bằng cách tham khảo.

+11

Tôi nghĩ bằng chứng này là sự hiểu sai. Có vẻ như bạn đang cố trao đổi tài liệu tham khảo. Bạn có vấn đề với cách các đối tượng được gán. Bạn đang chỉ định lại tham chiếu không thay đổi. Đó là giá trị nó trỏ đến mà có thể được thay đổi từ bên trong. Định nghĩa lại hoán đổi hiện đang chuyển ** x, cho phép bạn thay đổi * x. Vấn đề là trong suy nghĩ rằng $ x = $ y sẽ thay đổi những gì $ x ban đầu trỏ đến. – grantwparks

+3

* Đây không phải là bằng chứng *. Đầu ra của ví dụ đầu tiên là chính xác những gì bạn mong đợi nếu giá trị hiện tại của toàn bộ đối tượng được chuyển đến hàm 'swap'; nói cách khác, nếu các đối tượng được "truyền theo giá trị". Mặt khác, nó cũng chính xác những gì bạn mong đợi nếu một đối tượng xử lý được truyền cho hàm, đó thực sự là những gì sẽ xảy ra. Mã của bạn không phân biệt giữa hai trường hợp này. – EML

5

Bạn có thể thực hiện theo cách này.

đặt biểu tượng '&' ở phía trước và biến bạn đang truyền trở thành một và giống với điểm gốc của nó. tức là: bạn có thể vượt qua bằng cách tham khảo, thay vì tạo một bản sao của nó.

nên

$fred = 5; 
    $larry = & $fred; 
    $larry = 8; 
    echo $fred;//this will output 8, as larry and fred are now the same reference. 
+2

Điều này không được chấp nhận và tạo cảnh báo – fijiaaron

1

Đối tượng được truyền bằng tham chiếu trong PHP 5 và theo giá trị trong PHP 4. biến được truyền theo giá trị mặc định!

đọc ở đây: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html

+0

"Đối tượng" không phải là giá trị trong PHP5 và không thể "được chuyển". Tất cả các biến được truyền theo giá trị nếu tham số của hàm được truyền tới không có '&'. – newacct

+0

@newacct không hoàn toàn? Các đối tượng được [phần nào được chuyển qua tham chiếu] (http://php.net/manual/en/language.oop5.references.php). Tôi nghĩ rằng tôi đã quan sát thấy rằng các đối tượng php có thể được sửa đổi bởi các hàm ngay cả khi không được định nghĩa với '&' trước các tham số trong định nghĩa - nếu chúng được truyền bởi giá trị đối tượng chứa trong phạm vi gọi là hàm với nó một tham số sẽ không bị ảnh hưởng. –

+2

@ FélixGagnon-Grenier: Một lần nữa, "đối tượng" không phải là giá trị và không thể "được chuyển". Bạn không thể có một "biến" trong PHP5 có giá trị là một "đối tượng", bạn chỉ có thể có một giá trị là một tham chiếu đối tượng (tức là một con trỏ đến một đối tượng). Tất nhiên bạn có thể vượt qua hoặc gán một con trỏ cho một đối tượng theo giá trị và sửa đổi đối tượng mà nó trỏ đến bằng cách gọi một phương thức làm thay đổi. Điều đó không liên quan gì đến việc chuyển qua tham chiếu. Loại giá trị là gì và liệu tham số có được truyền theo giá trị/thông qua tham chiếu hay không là các thứ độc lập và trực giao. – newacct

1
class Holder 
{ 
    private $value; 

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

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

    public function setValue($value) 
    { 
     return $this->value = $value; 
    } 
} 

class Swap 
{  
    public function SwapObjects(Holder $x, Holder $y) 
    { 
     $tmp = $x; 

     $x = $y; 

     $y = $tmp; 
    } 

    public function SwapValues(Holder $x, Holder $y) 
    { 
     $tmp = $x->getValue(); 

     $x->setValue($y->getValue()); 

     $y->setValue($tmp); 
    } 
} 


$a1 = new Holder('a'); 

$b1 = new Holder('b'); 



$a2 = new Holder('a'); 

$b2 = new Holder('b'); 


Swap::SwapValues($a1, $b1); 

Swap::SwapObjects($a2, $b2); 



echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>"; 

echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>"; 

Thuộc tính vẫn còn thay đổi được khi không được thông qua bằng cách tham khảo nên hãy cẩn thận.

Output:

SwapObjects: b, a SwapValues: a, b

36

Trong PHP, bởi đối tượng mặc định được thông qua như là bản sao tham chiếu đến một đối tượng mới.

Xem ví dụ này .............

class X { 
    var $abc = 10; 
} 

class Y { 

    var $abc = 20; 
    function changeValue($obj) 
    { 
    $obj->abc = 30; 
    } 
} 

$x = new X(); 
$y = new Y(); 

echo $x->abc; //outputs 10 
$y->changeValue($x); 
echo $x->abc; //outputs 30 

Bây giờ thấy điều này ..............

class X { 
    var $abc = 10; 
} 

class Y { 

    var $abc = 20; 
    function changeValue($obj) 
    { 
    $obj = new Y(); 
    } 
} 

$x = new X(); 
$y = new Y(); 

echo $x->abc; //outputs 10 
$y->changeValue($x); 
echo $x->abc; //outputs 10 not 20 same as java does. 

Bây giờ, hãy xem điều này ..............

class X { 
    var $abc = 10; 
} 

class Y { 

    var $abc = 20; 
    function changeValue(&$obj) 
    { 
    $obj = new Y(); 
    } 
} 

$x = new X(); 
$y = new Y(); 

echo $x->abc; //outputs 10 
$y->changeValue($x); 
echo $x->abc; //outputs 20 not possible in java. 

tôi hy vọng bạn có thể hiểu điều này.

+0

Điều này minh họa rất rõ cách đối tượng PHP xử lý các công trình. –

+0

Ví dụ đầu tiên, giá trị của tham chiếu của obj được chuyển đến hàm, các thay đổi đối với obj bằng cách sử dụng tham chiếu mới sẽ phản ánh tất cả các tham chiếu khác trỏ đến cùng một obj.Ví dụ thứ hai, một lần nữa giá trị tham chiếu của obj được chuyển đến hàm, hàm đang thay đổi giá trị của tham chiếu để trỏ đến obj mới, obj cũ vẫn giữ nguyên. 3rd ex, tham chiếu giá trị của tham chiếu của obj được chuyển vào hàm, do đó các thay đổi trong hàm đang hoạt động trên cùng một obj. –

7

Bạn có thể chuyển một biến cho hàm theo tham chiếu.Hàm này sẽ có thể sửa đổi biến ban đầu.

Bạn có thể xác định những đoạn văn bằng cách tham chiếu trong định nghĩa hàm:

<?php 
function changeValue(&$var) 
{ 
    $var++; 
} 

$result=5; 
changeValue($result); 

echo $result; // $result is 6 here 
?> 
0

Trên thực tế cả hai phương pháp có giá trị nhưng nó phụ thuộc vào giá trị requirement.Pass của bạn bằng cách tham khảo thường làm cho kịch bản của bạn chậm. Vì vậy, nó tốt hơn để vượt qua các biến theo giá trị bằng cách xem xét thời gian thực hiện. Ngoài ra, lưu lượng mã nhất quán hơn khi bạn chuyển các biến theo giá trị.

Các vấn đề liên quan