Apakah variabel PHP diteruskan oleh nilai atau dengan referensi?
Apakah variabel PHP diteruskan oleh nilai atau dengan referensi?
Jawaban:
Ini berdasarkan nilai menurut Dokumentasi PHP .
Secara default, argumen fungsi dilewatkan oleh nilai (sehingga jika nilai argumen di dalam fungsi diubah, itu tidak bisa diubah di luar fungsi). Untuk memungkinkan suatu fungsi memodifikasi argumennya, mereka harus dilewatkan dengan referensi.
Agar argumen ke suatu fungsi selalu dilewatkan oleh referensi, tambahkan sebuah ampersand ( & ) ke nama argumen dalam definisi fungsi.
<?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.'
?>
$str = add_some_extra($str);
jika saya tidak menggunakan referensi, kan? lalu apa nilai tambah nyata dari itu?
$str
akan ditugaskan nol, dalam kasus Anda.
Dalam PHP, secara default objek dilewatkan sebagai salinan referensi ke objek baru.
Lihat contoh ini .............
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
Sekarang lihat ini ..............
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.
Sekarang lihat ini ..............
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.
saya harap kamu bisa mengerti ini.
$y
tidak diperlukan - tidak ada di function changeValue
dalamnya yang mengharuskannya berada di dalam class Y
, sehingga menyatukan dua konsep yang tidak terkait. Saya akan pindah function changeValue
ke lingkup luar, tepat di atas $x = new X();
. Hapus semua referensi $y
. Sekarang lebih mudah untuk melihat bahwa dua contoh pertama meninggalkan $ x sendirian, dan yang ketiga mengubah isinya new Y()
. Yang akan lebih mudah untuk melihat apakah Anda membuang type
dari $x
- fakta bahwa kedua X
dan Y
terjadi untuk menyertakan $abc
lapangan juga tidak relevan dengan apa yang ditunjukkan
Tampaknya banyak orang menjadi bingung dengan cara benda dilewatkan ke fungsi dan apa artinya lewat referensi. Variabel objek masih dilewati oleh nilai, hanya saja nilai yang diteruskan dalam PHP5 adalah pegangan referensi. Sebagai bukti:
<?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";
Keluaran:
a, b
Untuk lulus dengan referensi berarti kita dapat memodifikasi variabel yang dilihat oleh pemanggil. Yang jelas kode di atas tidak bisa. Kita perlu mengubah fungsi swap ke:
<?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";
Keluaran:
b, a
untuk melewati referensi.
swap
fungsi; dengan kata lain, jika objek "dilewati oleh nilai". Di sisi lain, itu juga persis seperti yang Anda harapkan jika sebuah pegangan objek dilewatkan ke fungsi, yang sebenarnya yang terjadi. Kode Anda tidak membedakan antara dua kasus ini.
http://www.php.net/manual/en/migration5.oop.php
Di PHP 5 ada Model Objek baru. Penanganan objek PHP telah sepenuhnya ditulis ulang, memungkinkan kinerja yang lebih baik dan lebih banyak fitur. Dalam versi PHP sebelumnya, objek ditangani seperti tipe primitif (misalnya integer dan string). Kelemahan dari metode ini adalah bahwa secara semantik seluruh objek disalin ketika variabel ditugaskan, atau diteruskan sebagai parameter ke metode. Dalam pendekatan baru, objek direferensikan oleh pegangan, dan bukan oleh nilai (orang dapat menganggap pegangan sebagai pengidentifikasi objek).
Variabel PHP ditugaskan oleh nilai, diteruskan ke fungsi dengan nilai, dan ketika berisi / mewakili objek dilewatkan oleh referensi. Anda dapat memaksa variabel untuk lulus dengan referensi menggunakan &
Ditugaskan oleh nilai / contoh referensi:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
akan menghasilkan
var1: tes, var2: tes akhir, var3: tes akhir
Lulus oleh nilai / referensi contoh:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
akan menghasilkan:
v1: foo, var2 BAR
Variabel objek yang dilewatkan oleh contoh referensi:
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";
}
Akan menghasilkan:
FOO
(contoh terakhir itu mungkin lebih baik ...)
$foo
adalah pointer ke objek . $foo
adalah lewat nilai ke fungsi changeFoo()
, seperti changeFoo()
tidak menyatakan parameter yang dengan &
.
Anda bisa meneruskan variabel ke fungsi dengan referensi. Fungsi ini akan dapat memodifikasi variabel asli.
Anda dapat mendefinisikan bagian dengan referensi dalam definisi fungsi:
<?php
function changeValue(&$var)
{
$var++;
}
$result=5;
changeValue($result);
echo $result; // $result is 6 here
?>
Anda dapat melakukannya dengan cara apa pun.
letakkan simbol '&' di depan dan variabel yang Anda lewati menjadi satu dan sama dengan asalnya. yaitu: Anda dapat melewati referensi, daripada membuat salinannya.
begitu
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
Variabel yang mengandung tipe primitif diteruskan oleh nilai dalam PHP5. Variabel yang berisi objek dilewatkan dengan referensi. Ada artikel yang cukup menarik dari Linux Journal dari 2006 yang menyebutkan ini dan perbedaan OO lainnya antara 4 dan 5.
&
.
Objek dilewatkan dengan referensi dalam PHP 5 dan dengan nilai dalam PHP 4. Variabel dilewatkan oleh nilai secara default!
Baca di sini: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
&
.
&
di depan parameter dalam definisi - jika mereka diteruskan oleh nilai objek yang terdapat dalam lingkup yang disebut fungsi dengan itu sebagai parameter akan tidak terpengaruh.
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>";
Atribut masih dapat dimodifikasi ketika tidak dilewati oleh referensi jadi waspadalah.
Keluaran:
SwapObjects: b, a SwapValues: a, b
Bagi siapa saja yang menemukan ini di masa mendatang, saya ingin membagikan permata ini dari dokumen PHP, yang diposting oleh pengguna anonim :
Tampaknya ada beberapa kebingungan di sini. Perbedaan antara petunjuk dan referensi tidak terlalu membantu. Perilaku dalam beberapa contoh "komprehensif" yang sudah diposting dapat dijelaskan dengan istilah pemersatu yang lebih sederhana. Kode Hayley, misalnya, melakukan PERSIS apa yang seharusnya Anda harapkan. (Menggunakan> = 5.3)
Prinsip pertama: Pointer menyimpan alamat memori untuk mengakses objek. Setiap kali suatu objek ditetapkan, sebuah pointer dihasilkan. (Saya belum menggali terlalu dalam ke mesin Zend, tapi sejauh yang saya bisa lihat, ini berlaku)
Prinsip 2, dan sumber yang paling membingungkan: Melewati variabel ke fungsi dilakukan secara default sebagai pass nilai, yaitu, Anda bekerja dengan salinan. "Tapi benda-benda dilewatkan dengan referensi!" Kesalahpahaman umum di sini dan di dunia Jawa. Saya tidak pernah mengatakan salinan APA. Pengoperan default dilakukan berdasarkan nilai. Selalu. APA yang sedang disalin dan dilewati, adalah penunjuknya. Saat menggunakan "->", Anda tentu saja akan mengakses internal yang sama dengan variabel asli dalam fungsi pemanggil. Hanya menggunakan "=" hanya akan bermain dengan salinan.
Prinsip 3: "&" secara otomatis dan permanen menetapkan nama variabel lain / penunjuk ke alamat memori yang sama dengan yang lain sampai Anda memisahkannya. Benar menggunakan istilah "alias" di sini. Anggap saja bergabung dengan dua petunjuk di pinggul sampai dipisahkan secara paksa dengan "tidak disetel ()". Fungsionalitas ini ada dalam lingkup yang sama dan saat argumen dilewatkan ke suatu fungsi. Seringkali argumen yang diteruskan disebut "referensi," karena perbedaan tertentu antara "lewat nilai" dan "lewat referensi" yang lebih jelas dalam C dan C ++.
Ingat saja: pointer ke objek, bukan objek itu sendiri, diteruskan ke fungsi. Pointer ini adalah SALINAN dari yang asli kecuali Anda menggunakan "&" di daftar parameter Anda untuk benar-benar melewati aslinya. Hanya ketika Anda menggali bagian dalam suatu objek, dokumen aslinya akan berubah.
Dan inilah contoh yang mereka berikan:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}
?>
Saya menulis posting blog yang luas dan terperinci tentang subjek ini untuk JavaScript , tetapi saya percaya itu berlaku juga untuk PHP, C ++, dan bahasa lain di mana orang-orang tampaknya bingung tentang nilai demi nilai vs per referensi.
Jelas, PHP, seperti C ++, adalah bahasa yang mendukung referensi per referensi. Secara default, objek dilewatkan oleh nilai. Ketika bekerja dengan variabel yang menyimpan objek, ada baiknya untuk melihat variabel-variabel itu sebagai pointer (karena pada dasarnya seperti apa mereka, di tingkat perakitan). Jika Anda melewatkan pointer berdasarkan nilai, Anda masih bisa "melacak" pointer dan memodifikasi properti objek yang ditunjuk. Yang tidak bisa Anda lakukan adalah mengarahkannya ke objek lain. Hanya jika Anda secara eksplisit mendeklarasikan parameter yang dilewatkan oleh referensi Anda akan dapat melakukannya.
Sebenarnya kedua metode ini valid tetapi tergantung pada kebutuhan Anda. Nilai-nilai kecepatan dengan referensi sering membuat skrip Anda lambat. Jadi lebih baik untuk melewatkan variabel berdasarkan nilai dengan mempertimbangkan waktu eksekusi. Alur kode juga lebih konsisten ketika Anda melewatkan variabel berdasarkan nilai.
Gunakan ini untuk fungsi ketika Anda hanya ingin mengubah variabel asli dan mengembalikannya ke nama variabel yang sama dengan nilai baru yang ditetapkan.
function add(&$var){ // The & is before the argument $var
$var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
Bergantung pada versi, 4 berdasarkan nilai, 5 berdasarkan referensi.