Php’de Referanslar

Merhaba,

PHP ‘de referanslar, sık kullanımını görmesek de aslında bilmemizde yararı olan şeyler. Daha önce C veya C++ ile uğraştıysanız referansları göstericiler ile aynı kefeye koyabilirsiniz. Nitekim aynı olmadıklarını da göz ardı etmemelisiniz. PHP ‘de referansları daha çok başka bir değişkene ulaşmak için gereken kısa yol gibi düşünebilirsiniz ve *NIX sistemlerinde ?hardlinking? ‘e benzetebilirsiniz.

<?php
$asil = 'Ali ata bak';
$kopya = &$asil;
echo $kopya;
?>

Yukarıda göründüğü üzere $kopya değişkenine $asil değişkeninin değeri reference sayesinde atanıyor. Reference işareti olarak ‘&’ işaretini kullanıyoruz. Referansları diziler ile de kullanabiliriz, örnek:

<?php
$asil[0] = 'Oya Ata Bak';
$asil[1] = 'Ali ata bak';
$kopya = &$asil;
print_r($kopya);
?>

Ayrıca aşağıda görülen referans edilen değişkenin referansı da doğru bir tanımlamadır:

<?php
$asil = 'Ali ata bak';
$kopya = &$asil;
$kopya2 = &$kopya;
echo $kopya2;
?>

Referanslar birbirine tür ve içerik olarak tam anlamıyla eşittir:

<?php
$asil = 'Ali ata bak';
$kopya = &$asil;
if ($kopya === $asil) echo "eşitlik var";
else echo "eşitlik yok";
?>

Yukarıdaki kod size hep eşitlik var değerini verecektir. Not: ‘===’ operatörü == ‘nın işlevi yanında değişkenlerin türlerinin de aynı olup olmadığına bakar.

Ek bilgi:
C bilmeyenler için & işaretinin anlamını kaydedelim. & işareti C ‘de verilen değişkenin hafıza üzerine bulunduğu yerin adresini verir. C ‘ de göstericileri kullanmak için özel bir türde nesne yaratılır ve nesnenin başına * koyarak adresi alınan nesnenin içeriğine ulaşılabilir. Örnek olarak bir kod yazalım:

#include

int main(void) {
int *i, p=1;
i = &p;
printf(“İcerik: %d n Adresi: %d”,*i,i);
return 0;
}

PHP ‘de gördüğünüz üzere ‘*’ işaretinin kullanımı söz konusu değildir ve PHP ‘de memory adresi değişkene atanmaz referans sadece bir kısayoldur.

REFERANSLARIN ÖMÜRLERİ

Aşağıdaki kodu inceliyoruz:

<?php
$asil = 'Ali ata bak';
$kopya = &$asil;
echo $kopya;
echo $asil;
$asil = 'Kaya ata bak';
echo $kopya;
echo $asil;
$kopya = 'Oya ata bak';
echo $kopya;
echo $asil;
?>

Yukarıda kodu çalıştırdığınızda da göreceğiniz üzere, $asil ya da $kopya değişkenini değiştirdiğinizde, değer de her durumda değişiyor. Ama unutmamız gereken bir nokta var, $kopya ve $asil aynı değere sahip farklı değişkenlerdir. Yani içindeki değer dışında değişkene bir işlem yaptığımızda ortadaki değer kaybolmaz! Aşağıdaki kodu inceliyoruz:

<?php
$asil = 1;
$kopya = &$asil;
unset($asil);
echo $kopya;
?>

Yukarıda $asil ya da $kopya değişkenini unset ile yok etmemiz ortadaki değerin yok olmasını sağlamaz. İki değişkenden birini unset ettiğimizde diğerinin değeri değişmeden kalır.

Global olarak fonksiyonun içine aldığımız değerlerin ömürleri ne olacak? Hadi bakalım:

<?php
$deger1 = "Ornek degisken";
$deger2 = "";

function fonksiyon() {
global $deger1, $deger2;
$deger2 = &$deger1;
}

fonksiyon();
echo "$deger2";
?>

Böyle bir durumda $deger2 ‘nin dışarıdaki değeri değişmeyecektir. Çünkü fonksiyonun içinde yapılan işlem fonksiyona aittir. Eğer $deger2 değişkeninin değerini dışarda da değiştirmek istiyorsak aşağıdaki yöntemi uygulayabiliriz:

<?php
$deger1 = "Ornek degisken";
$deger2 = "";

function global_referanslar() {
global $deger1, $deger2;
$GLOBALS["deger2"] = &$deger1;
}

global_references();
echo "$deger2";
?>

Daha önce referanslar ile uğraşanların ve C bilenlerin aklına bunun bir yöntemi daha olduğu akıllarına gelebilir, nitekim ileride ele alacağımız bir durum olacak, onun için aklınıza geldiyse unutmayın 🙂

Ek Bilgi:
Referansların gösterici (pointer) olmadıklarını unutmayın, aşağıdaki kod beklediğiniz gibi çalışmayacaktır:

<?php
$deger =1;
function fonksiyon(&$ic) {
$ic = &$GLOBALS["deger2"];
}
foo($deger);
echo $deger2;
?>

Yukarda $deger2 ‘nin içine değer atanmadığını göreceksiniz. Oysaki C ‘de göstericiler ile böyle bir şey yapmak mümkündür.

FONKSİYONLAR İLE REFERANS KULLANIMI
Basit olarak referansların ne olduğunu gördük şimdi asıl mevzumuza gelelim, referansların fonksiyonlar ile kullanımına.

Yukarıda önceden unutmayın dediğim şey vardı ya şimdi oraya geldik, yani global değişkenleri direkt uğraşmadan değiştirmeye:

<?php
function fonksiyon(&$ic_deger) {
$ic_deger++;
}
$deger=5;
fonksiyon($deger);
echo $deger;
?>

Yukarıdaki $deger ‘in son değerinin ‘6’ olduğunu göreceksiniz. C ile uğraşmış kişiler için bu şaşırtıcı gelmiyor olabilir. Ama biz bilmeyenler için biraz derine inelim. Fonksiyonu yukarıdaki gibi tanımlamak fonksiyonun içindeki $ic_deger ile $deger değişkeninin içeriğini fonksiyon içinde birbirine bağlamaktır. $ic_deger ve $deger değişkenleri fonksiyon içinde aynı içeriğe yönlendirilmişlerdir. $ic_deger bu içeriği değiştirdiğinde doğal olarak $deger değişkeninin içeriğinin de değiştirmiş olacağından $deger global değişkeninin içeriği de $ic_deger++; işlemi sonunda değişmiş olacak.

Yukarıdaki olay aklınızı karıştırdıysa üzülmeyin birkaç kez okuyup uygulama yapın anlayacaksınız.

Ek Bilgi:

İşe yarayacağını düşünmediğim bir özellik olan reference return olayını da ele alalım ve aşağıdaki kodu inceleyelim.

<?php
function &fonksiyon($sayi){
$var = &$sayi;
$sayi *= $sayi;
return $var;
}
$sonuc = &fonksiyon(5);
echo $sonuc;

?>

Bu basit örneği sadece kuralı göstermek için yazdım. Fonksiyon tanımının başına ‘&’ koymak fonksiyonun referans olan bir değer döndürdüğünün göstergesidir eğer bunu aşağıdaki gibi kullanırsanız,

<?php
function &fonksiyon($sayi){
$var = &$sayi;
return $var*$var;
}
$sonuc = &fonksiyon(5);
echo $sonuc;

?>

“Notice: Only variable references should be returned by reference in /usr/vs/vs/reference.php on line xx” haberini alırsınız çünkü $var*$var bir reference belirtmez. Ama sonuç yine dönecektir.

Ayrıca lütfen değişkene değer atarken de ‘&’ kullanmamıza dikkat edin. İşleri biraz daha karıştıralım 🙂


<?php
$sonuc = 4;
function &fonksiyon(&$sayi){
$sayi *= $sayi;
return $sayi;
}
$sonuc2 = &fonksiyon($sonuc);
echo $sonuc;
echo $sonuc2
?>

Bu kodu incelerseniz çıktının 1616 olduğunu göreceksiniz.

Dikkat: Normalde referans döndürüyorsanız fonksiyonda ‘&’ karakteri kullanmanıza gerek yok, PHP bunu zaten kendi anlayabilecek kapasitede. Bunun için ekstra bilgi kısmında ya zaten 🙂 Aşağıdaki kod yukardaki ile aynı işlevi görecektir ve hiçbir notice hata vs. vermeyecektir.

<?php
$sonuc = 4;
function fonksiyon(&$sayi){
$sayi *= $sayi;
return $sayi;
}
$sonuc2 = fonksiyon($sonuc);
echo $sonuc;
echo $sonuc2
?>

Bu olay PHP5 ‘te kaldırılmıştır ve ‘&’ kullanırsanız size E_STRICT düzeyinde bir hata mesajı verecektir. Aynı durum sadece fonksiyonlar için değil sınıflar için de geçerlidir.

Fonksiyonlarda global anahtar kelimesi aslında $degisken = &$GLOBALS[“degisken”]; ile aynı görevi görür. $degisken değerini unset ettiğimizde global değişken de unset edilmez. Peki ya direkt $degisken = $GLOBALS[“degisken”]; yazarsak fark ne olur. Bu en güzel bir örnekle anlatılır değil mi 🙂

<?php
$sayi = 4;
function fonksiyon(){
$sayi = $GLOBALS["sayi"];
$GLOBALS["sayi"] = 5;
echo $sayi;
}

fonksiyon();
?>

bu kod ekrana 4 yazdırıyorken;

<?php
$sayi = 4;
function fonksiyon(){
$sayi = &$GLOBALS["sayi"];
$GLOBALS["sayi"] = 5;
echo $sayi;
}

fonksiyon();
?>

bu kod ekrana 5 yazdıracaktır.

Be the first to comment

Leave a Reply

Your email address will not be published.


*