PHP değişkenleri değere veya referansa göre mi aktarılıyor?
PHP değişkenleri değere veya referansa göre mi aktarılıyor?
Yanıtlar:
PHP Belgelerine göre değerlidir .
Varsayılan olarak, işlev bağımsız değişkenleri değere göre iletilir (böylece işlev içindeki bağımsız değişkenin değeri değiştirilirse, işlevin dışında değiştirilmez). Bir işlevin bağımsız değişkenlerini değiştirmesine izin vermek için, bunların başvuru ile iletilmesi gerekir.
Her zaman başvuru ile iletilen bir işlevin bağımsız değişkenine sahip olmak için , işlev tanımındaki bağımsız değişken adına bir ve işareti ( & ) ekleyin .
<?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);
gerekirse, bu referansı kullanmıyormuşum gibi olurdu, değil mi? o zaman bunun gerçek katma değeri nedir?
$str
durumda sizin durumunuzda null atanır.
PHP'de, varsayılan olarak nesneler yeni bir Nesneye başvuru kopyası olarak iletilir.
Bu örneğe bakın .............
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
Şimdi şuna bakın ..............
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.
Şimdi şuna bakın ..............
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.
umarım bunu anlayabilirsin.
$y
gerekli değildir - içinde function changeValue
olmasını gerektiren hiçbir şey yoktur class Y
, böylece iki ilgisiz kavramı birbirine bağlar. function changeValue
Hemen hemen dış kapsama giderdim $x = new X();
. İçin tüm referansları kaldırın $y
. İlk iki örneğin $ x 'ı yalnız bıraktığını ve üçüncüsünün içeriğini değiştirdiğini görmek artık daha kolay new Y()
. Terk olmadığını görmek için daha kolay olurdu hangisi type
arasında $x
- hem gerçeği X
ve Y
bir içerecek şekilde gerçekleşmesi $abc
alanını da kanıtlanmıştır alakasız olduğunu
Pek çok insan, nesnelerin işlevlere aktarılma şekli ve referansla geçenlerin ne anlama geldiği ile karıştırılmaktadır. Nesne değişkenleri hala değere göre iletilir, sadece PHP5'te iletilen değer bir referans tanıtıcısıdır. Kanıt olarak:
<?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";
Çıktılar:
a, b
İçin referans geçmek şekilde işin arayan tarafından görülen değişkenlerin değiştirebilir. Hangi açıkça yukarıdaki kodu yapmaz. Takas işlevini şu şekilde değiştirmemiz gerekir:
<?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";
Çıktılar:
b, a
referans ile geçmek için.
swap
işleve geçirilmesi durumunda tam olarak beklediğiniz değerdir ; diğer bir deyişle, nesneler "değere göre aktarılmışsa". Öte yandan, bir nesne tutamacının işleve geçirilmesini beklediğiniz de tam olarak budur. Kodunuz bu iki durum arasında ayrım yapmaz.
http://www.php.net/manual/en/migration5.oop.php
PHP 5'te yeni bir Nesne Modeli vardır. Daha iyi performans ve daha fazla özellik için PHP'nin nesneleri kullanması tamamen yeniden yazılmıştır. PHP'nin önceki sürümlerinde, nesneler ilkel türler (örneğin tamsayılar ve dizeler) gibi ele alındı. Bu yöntemin dezavantajı, bir değişken atandığında tüm nesnenin anlamsal olarak kopyalanması veya bir yönteme parametre olarak geçirilmesiydi. Yeni yaklaşımda, nesnelere değere göre değil, tanıtıcıya başvurulur (tanıtıcı bir nesnenin tanımlayıcısı olarak düşünülebilir).
PHP değişkenleri değere göre atanır, işlevlere değere göre iletilir ve nesneleri içeren / temsil ederken başvuru ile iletilir. Değişkenleri bir &
Değer / referans örneğiyle atanır:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
çıktı
var1: test, var2: son test, var3: son test
Değer / referans sınavıyla geçti:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
çıktı:
var1: foo, var2 BAR
Referans muayene ile geçirilen nesne değişkenleri:
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";
}
Çıktı:
FOO
(bu son örnek muhtemelen daha iyi olabilir ...)
$foo
bir göstericidir . $foo
bir değer geçirilecek işleve changeFoo()
olarak, changeFoo()
bir ile parametresini belirtmezdi &
.
Her iki şekilde de yapabilirsiniz.
önüne bir '&' sembolü koyun ve geçtiğiniz değişken kökeniyle bir ve aynı olur. yani: bir kopyasını almak yerine referans ile geçebilirsiniz.
yani
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
İlkel türler içeren değişkenler PHP5 içindeki değere göre geçirilir. Nesneleri içeren değişkenler referans ile iletilir. 2006'dan itibaren Linux Journal'dan bu ve 4 ile 5 arasındaki diğer OO farklılıklarından bahseten ilginç bir makale var.
&
.
Nesneler, PHP 5'te başvuru ve PHP 4'te değere göre geçirilir. Değişkenler varsayılan olarak değere göre iletilir!
Burayı okuyun: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
&
.
&
tanımındaki parametrelerin önünde ile tanımlanmamış olsa bile işlevler tarafından değiştirilebileceğini gözlemledim - değer olarak geçerse, bir parametre olarak işlev olarak adlandırılan kapsamda yer alan nesne etkilenmez.
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>";
Özellikler referans ile geçilmediğinde hala değiştirilebilir, bu yüzden dikkatli olun.
Çıktı:
SwapObjects: b, a TakasDeğerleri: a, b
Gelecekte bununla karşılaşan herkes için, bu gem anonim bir kullanıcı tarafından yayınlanan PHP belgelerinden paylaşmak istiyorum :
Burada bir karışıklık var gibi görünüyor. İşaretçiler ve referanslar arasındaki ayrım özellikle yararlı değildir. Daha önce yayınlanmış olan bazı "kapsamlı" örneklerin davranışı daha basit birleştirici terimlerle açıklanabilir. Örneğin Hayley'in kodu TAMAMEN yapması gerekeni TAMAMEN yapıyor. (> = 5.3 kullanılarak)
İlk ilke: Bir işaretçi bir nesneye erişmek için bir bellek adresi depolar. Bir nesne atandığında, bir işaretçi oluşturulur. (Zend motorunu henüz derinlemesine araştırmadım, ancak görebildiğim kadarıyla bu geçerli)
2. ilke ve en karışıklığın kaynağı: Bir değişkenin bir işleve geçirilmesi varsayılan olarak bir değer geçirme olarak yapılır, yani bir kopya ile çalışıyorsunuz. "Ama nesneler referansla geçti!" Hem burada hem de Java dünyasında yaygın bir yanlış anlama. Ben NE OLDUĞUN bir kopyasını söylemedim. Varsayılan geçiş, değere göre yapılır. Her zaman. Bununla birlikte, işaretçi ne kopyalanır ve iletilir. "->" kullanırken, elbette, arayan işlevindeki orijinal değişkenle aynı iç yapılara erişeceksiniz. Yalnızca "=" kullanıldığında yalnızca kopyalarla oynatılır.
3. ilke: "&", siz onu ayırana kadar başka bir değişken adını / işaretçisini başka bir şeyle aynı bellek adresine otomatik ve kalıcı olarak ayarlar. Burada "takma ad" terimini kullanmak doğrudur. Bunu "unset ()" ile zorla ayrılana kadar kalçada iki işaretçi olarak birleştirmeyi düşünün. Bu işlevsellik hem aynı kapsamda hem de bir işleve bir argüman iletildiğinde bulunur. Genellikle "bağımsız değişken", "değere göre geçme" ile "referans ile geçme" arasında C ve C ++ 'da daha açık olan belirli ayrımlar nedeniyle "başvuru" olarak adlandırılır.
Unutmayın: nesnelere değil nesnelerin işaretçileri işlevlere aktarılır. Orijinalleri gerçekten iletmek için parametre listenizde "&" kullanmadığınız sürece bu işaretçiler orijinalin KOPYA SAYISIDIR. Yalnızca bir nesnenin içinin içine girdiğinizde orijinaller değişir.
Ve işte verdikleri örnek:
<?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.
}
?>
JavaScript için bu konuda kapsamlı, ayrıntılı bir blog yazısı yazdım , ancak PHP, C ++ ve insanların değere göre geçişe göre referansla karıştığı başka bir dil için de aynı derecede geçerli olduğuna inanıyorum.
Açıkçası, PHP, C ++ gibi, referans ile geçişi destekleyen bir dildir. Varsayılan olarak, nesneler değere göre iletilir. Nesneleri depolayan değişkenlerle çalışırken, bu değişkenleri işaretçi olarak görmeye yardımcı olur (çünkü montaj seviyesinde temelde oldukları şey budur). Bir işaretçiyi değere göre iletirseniz, işaretçiyi yine de "izleyebilir" ve işaretlenen nesnenin özelliklerini değiştirebilirsiniz. Yapamayacağınız şey, farklı bir nesneye işaret etmesidir. Yalnızca bir parametreyi referans olarak iletildiğini açıkça belirtirseniz, bunu yapabilirsiniz.
Aslında her iki yöntem de geçerlidir, ancak gereksiniminize bağlıdır. Referansa göre pas değerleri genellikle komut dosyanızı yavaşlatır. Bu nedenle, yürütme süresini dikkate alarak değişkenleri değere göre geçirmek daha iyidir. Ayrıca değişkenlere göre değer ilettiğinizde kod akışı daha tutarlıdır.
Orijinal değişkeni basitçe değiştirmek ve yeni değeri atanmış olarak tekrar aynı değişken adına döndürmek istediğinizde işlevler için bunu kullanın.
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
Versiyona bağlı olarak, 4 değere, 5 referansa göre.