PHP'de değişken, adının önüne dolar işareti ($) konan ve önceden bildirilmesi gerekmeyen bir isimdir: $ad = 'Ali'; satırı değişkeni hem oluşturur hem de değer atar. Değişken adları büyük-küçük harfe duyarlıdır, tipi içindeki değere göre belirlenir ve bir fonksiyonun içinde tanımlanan değişken yalnızca o fonksiyonda görünür. Fonksiyon dışındaki bir değişkene içeriden erişmek için global anahtar kelimesi veya $GLOBALS dizisi gerekir.

Bu yazıda adlandırma kurallarını, değerle atamanın anlamını, tanımsız değişkenlerin davranışını, kapsam (scope) kurallarını, static değişkenleri, değişken değişkenleri ve süper global dizileri çalıştırılmış örneklerle anlatıyoruz. Serinin diğer yazılarına PHP öğrenme rehberi sayfasından ulaşabilirsiniz.

Değişken adlandırma kuralları

Değişken adlandırma kuralları

Geçerli bir değişken adı bir harf veya alt çizgiyle başlar, ardından istediğiniz sayıda harf, rakam veya alt çizgi gelebilir. Kılavuz burada "harf" kavramını geniş tutar: A-Z ve a-z dışında 128 ile 255 arasındaki baytlar da harf sayılır. UTF-8'de çok baytlı her karakterin baytları bu aralığa düştüğü için $şehir veya $öğrenci gibi Türkçe karakterli adlar geçerlidir. Rakamla başlayan $4site gibi bir ad ise sözdizimi hatasıdır.

Adlar karakter olarak değil bayt olarak karşılaştırılır. Bu da ekranda aynı görünen iki adın farklı değişkenler olabileceği anlamına gelir; örneğin aynı harfin birleşik ve ayrık Unicode yazımları ya da sonunda görünmez bir bölünmez boşluk bulunan bir ad. Ekip içinde ASCII adlar kullanmak bu tür hataları baştan önler. $this ise özel bir değişkendir ve ona değer atanamaz.

php
<?php
$ad = 'Ali';
$Ad = 'Veli';
echo "$ad, $Ad\n";          // çıktı: Ali, Veli

$şehir = 'İzmir';           // UTF-8 harfler ad içinde geçerlidir
$_gecici = true;            // alt çizgiyle başlamak geçerlidir
echo $şehir, "\n";          // çıktı: İzmir

Değerle atama ve referansla atama

PHP'de atama varsayılan olarak değerle yapılır: $b = $a dediğinizde $a'nın değeri $b'ye kopyalanır ve sonrasında birini değiştirmek diğerini etkilemez. Bunun alternatifi referansla atamadır; kaynak değişkenin önüne & koyduğunuzda yeni değişken eskisinin takma adı olur ve ikisi aynı veriyi gösterir. Yalnızca adlandırılmış değişkenler referansla atanabilir; &(24 * 7) gibi bir ifade geçersizdir.

php
<?php
$a = 5;
$b = $a;      // değer kopyalanır
$b = 10;
echo $a, "\n"; // çıktı: 5

$c = &$a;     // $c artık $a'nın takma adı
$c = 7;
echo $a, "\n"; // çıktı: 7

Nesnelerde durum biraz farklıdır: bir nesneyi başka bir değişkene atadığınızda nesnenin kendisi değil ona erişim tutamacı kopyalanır, bu yüzden iki değişken aynı nesne üzerinde çalışır. Bu konu clone ve nesne karşılaştırma yazısında, referansların tüm ayrıntısı ve foreach içindeki tuzakları ise PHP referanslar yazısında anlatılıyor.

Tanımsız değişkenler, isset ve unset

PHP değişkenleri önceden bildirmenizi zorunlu tutmaz, ama kılavuz bunu iyi bir alışkanlık olarak önerir. Tanımlanmamış bir değişkeni okumak PHP 8.0'dan beri E_WARNING seviyesinde uyarı üretir (öncesinde E_NOTICE idi) ve değişkenin değeri null kabul edilir. Bir değişkenin tanımlı ve null olmayan bir değere sahip olup olmadığını uyarı almadan kontrol etmek için isset() kullanılır. unset() ise değişkeni yok eder.

Bir istisna vardır: tanımsız bir değişkene [] ile eleman eklemek uyarı vermez, PHP yeni bir dizi oluşturur. Kılavuz buna dizinin kendiliğinden oluşması (autovivification) der. Kullanışlı görünse de, aynı adı kullanan başka bir dosyayı include ettiğinizde önceden kalmış bir değerin üzerine yazma riski taşıdığı için kılavuz tanımsız değişkenin varsayılan değerine güvenmeye karşı uyarır.

php
<?php
var_dump($tanimsiz);
var_dump(isset($tanimsiz));

$liste[] = 'ilk';   // tanımsız değişkenden dizi oluşturur, uyarı vermez
var_dump($liste);

$x = 1;
unset($x);
var_dump(isset($x));
text
Warning: Undefined variable $tanimsiz in /yol/ornek.php on line 2
NULL
bool(false)
array(1) {
  [0]=>
  string(3) "ilk"
}
bool(false)

"Undefined variable" uyarısının dizi anahtarı ve nesne özelliği biçimleri ile ?? operatörüyle çözüm yolları undefined variable ve array key uyarısı yazısında ayrıca ele alınıyor.

Değişken kapsamı: global ve fonksiyon kapsamı

Değişken kapsamı: global ve fonksiyon kapsamı: include edilen dosyanın kapsamı, global anahtar kelimesi ve $GLOBALS dizisi, Anonim fonksiyonlarda kapsam

PHP'de iki temel kapsam vardır: global kapsam ve fonksiyon kapsamı. Herhangi bir fonksiyonun dışında tanımlanan değişken global kapsamdadır. Adlandırılmış bir fonksiyonun veya anonim fonksiyonun içinde oluşturulan değişken ise yalnızca o fonksiyonun gövdesinde yaşar. Bir dosya include edildiğinde, içindeki kod include satırının bulunduğu kapsamı devralır; fonksiyonun içinden yapılan bir include, dosyadaki değişkenleri o fonksiyonun yerel değişkenleri hâline getirir.

Bu noktada PHP, C dilinden ayrılır. C'de global değişkenler, yerel bir tanım onları gölgelemedikçe fonksiyonların içinden görünür. PHP'de ise fonksiyon içinden global bir değişkeni kullanmak istiyorsanız bunu açıkça belirtmeniz gerekir. Kılavuza göre bu tasarım, global bir değişkenin yanlışlıkla değiştirilmesini önler.

include edilen dosyanın kapsamı

Kapsam kuralının pratikte en çok şaşırtan yanı include ile ilgilidir. Eklenen dosya kendi kapsamını getirmez, include satırının bulunduğu kapsamı kullanır. Aşağıdaki örnek, tek satırlık bir yardımcı dosyayı geçici klasöre yazıp önce bir fonksiyonun içinden, sonra global kapsamdan yüklüyor. Fonksiyon içindeki include ile oluşan $renk, fonksiyon bitince kaybolur ve global kapsamda görünmez; aynı dosya global kapsamda yüklendiğinde ise değişken global olur.

php
<?php
$parca = sys_get_temp_dir() . '/tema_parcasi.php';
file_put_contents($parca, '<?php $renk = "lacivert";');

function temaYukle(string $dosya): string
{
    include $dosya;            // $renk bu fonksiyonun yerel değişkeni olur
    return $renk;
}

echo temaYukle($parca), "\n";  // çıktı: lacivert
var_dump(isset($renk));        // çıktı: bool(false)

include $parca;                // global kapsamda include
echo $renk, "\n";              // çıktı: lacivert
unlink($parca);

Bu davranış, şablon dosyalarını bir fonksiyon içinden yükleyerek şablonun yalnızca o fonksiyonun hazırladığı değişkenleri görmesini sağlamak için bilinçli olarak kullanılabilir. Tersine, global kapsamda çalışacağını varsayarak yazılmış eski bir dosyayı fonksiyon içinden yüklediğinizde, dosyanın tanımladığı değişkenler dışarıdan erişilemez hâle gelir ve "Undefined variable" uyarıları başlar. Böyle bir sorunla karşılaştığınızda önce dosyanın nereden yüklendiğine bakın.

global anahtar kelimesi ve $GLOBALS dizisi

global $sayac; satırı, fonksiyonun içinde global $sayac'a bağlı yerel bir referans oluşturur. Global değişken henüz yoksa global kapsamda oluşturulur ve null değerini alır. İkinci yol $GLOBALS süper global dizisidir; anahtarları global değişkenlerin adları, değerleri ise içerikleridir ve her kapsamdan erişilebilir.

php
<?php
$sayac = 10;

function oku()
{
    return $sayac;            // yerel $sayac tanımsız
}

function okuGlobal()
{
    global $sayac;            // global $sayac'a bağlanır
    $sayac++;
    return $sayac;
}

function okuGlobals()
{
    return $GLOBALS['sayac'];
}

var_dump(oku());
var_dump(okuGlobal());
var_dump(okuGlobals());
text
Warning: Undefined variable $sayac in /yol/ornek.php on line 6
NULL
int(11)
int(11)

İlk fonksiyon kendi yerel $sayac değişkenini aradığı için uyarı aldı. İkincisi global ile bağlanıp değeri 11'e çıkardı; üçüncüsü de bu güncel değeri $GLOBALS üzerinden okudu.

PHP 8.1 ile $GLOBALS dizisinin davranışı değişti: artık global sembol tablosunun salt okunur bir kopyasıdır. Tek bir anahtara yazmak ($GLOBALS['x'] = 3) hâlâ global değişkeni değiştirir, ancak dizinin tamamını başka bir değişkene kopyalayıp o kopya üzerinden değişiklik yapmak artık global değişkenleri etkilemez. Dizinin tamamına yazmak ($GLOBALS = [], unset($GLOBALS) gibi) ise derleme zamanında hata verir.

php
<?php
$x = 1;
$kopya = $GLOBALS;
$kopya['x'] = 2;    // PHP 8.1'den beri yalnızca kopyayı değiştirir
var_dump($x);       // çıktı: int(1)

$GLOBALS['x'] = 3;  // tek bir anahtara yazmak hâlâ çalışır
var_dump($x);       // çıktı: int(3)

Anonim fonksiyonlarda kapsam

Kapsam kuralının önemli bir istisnası arrow function'lardır. fn ile yazılan kısa fonksiyonlar, kullandıkları değişkenleri üst kapsamdan otomatik olarak alır. Klasik function () {} biçimindeki closure'larda ise dış değişkeni use ile açıkça içeri almanız gerekir.

php
<?php
$oran = 18;
$kdvli = fn($tutar) => $tutar * (1 + $oran / 100);   // arrow function üst kapsamı görür
echo $kdvli(100), "\n";                              // çıktı: 118

$kdvli2 = function ($tutar) use ($oran) {            // closure'da use gerekir
    return $tutar * (1 + $oran / 100);
};
echo $kdvli2(200), "\n";                             // çıktı: 236

İki sözdiziminin farkları, use ile referans yakalama ve birinci sınıf callable kullanımı anonim fonksiyon ve arrow function yazısında ayrıntılı olarak işleniyor.

static değişkenler

static ile tanımlanan bir değişken yalnızca fonksiyonun yerel kapsamında görünür, ancak fonksiyon bittiğinde değerini kaybetmez. İlk değer atama yalnızca ilk çağrıda yapılır; sonraki çağrılar kaldığı yerden devam eder. Bu özellik çağrı sayaçları, basit önbellekler ve özyinelemeli fonksiyonlarda derinlik takibi için kullanılır.

PHP 8.3'ten önce static değişkene yalnızca sabit bir ifade (ör. 0 veya 1 + 2) atanabiliyordu. PHP 8.3 ile fonksiyon çağrısı gibi dinamik ifadeler de ilk değer olarak kullanılabilir hâle geldi; aşağıdaki örneğin ikinci fonksiyonu bu yüzden PHP 8.3 veya sonrasını gerektirir.

php
<?php
function ziyaret()
{
    static $kez = 0;   // yalnızca ilk çağrıda 0 atanır
    $kez++;
    return "Ziyaret sayısı: $kez\n";
}

echo ziyaret();   // çıktı: Ziyaret sayısı: 1
echo ziyaret();   // çıktı: Ziyaret sayısı: 2
echo ziyaret();   // çıktı: Ziyaret sayısı: 3

function baslangic()
{
    static $ilk = strtoupper('hazir');   // PHP 8.3 ve sonrası: dinamik ilk değer
    return $ilk;
}
echo baslangic(), "\n";   // çıktı: HAZIR

İki ayrıntıyı bilmekte fayda var. Birincisi, anonim fonksiyon içindeki static değişken yalnızca o fonksiyon örneğine aittir; closure her çağrıda yeniden oluşturuluyorsa sayaç da her seferinde sıfırdan başlar. İkincisi, PHP 8.1'den beri bir metot miras alındığında (ama ezilmediğinde) üst sınıftaki metotla aynı static değişkeni paylaşır; yani statik değişkenler bu açıdan statik özellikler gibi davranır. Statik özellikler static ve late static binding yazısında anlatılıyor.

Değişken değişkenler ($$ad)

Değişken değişken, bir değişkenin değerini başka bir değişkenin adı olarak kullanmaktır. $alan = 'renk' iken $$alan = 'mavi' yazmak, $renk adında yeni bir değişken oluşturur. Dizilerle kullanıldığında belirsizlik doğar: $$a[1] ifadesinin $a[1] değerini değişken adı olarak mı, yoksa $$a değişkeninin 1 numaralı elemanını mı kastettiği anlaşılmaz. Kılavuz bunu süslü parantezle çözer: ilki için ${$a[1]}, ikincisi için ${$a}[1].

php
<?php
$alan = 'renk';
$$alan = 'mavi';          // $renk = 'mavi' ile aynı
echo $renk, "\n";         // çıktı: mavi
echo "{$$alan}\n";        // çıktı: mavi

$adlar = ['boy', 'kilo'];
${$adlar[0]} = 180;       // $boy = 180
echo $boy, "\n";          // çıktı: 180

Aynı fikir nesne özelliklerinde de çalışır: $nesne->$ozellik yazdığınızda $ozellik değişkeninin değeri özellik adı olarak kullanılır. json_decode() ile gelen ve PHP adı olarak geçersiz karakterler içeren özelliklere $nesne->{'ad-soyad'} biçiminde erişmek de bu sözdizimine dayanır.

Süper global dizilere kısa giriş

Süper global dizilere kısa giriş: $GLOBALS, $_SERVER, $_GET, $_POST

Bazı önceden tanımlı değişkenler "süper global"dir: her kapsamda kendiliğinden görünürler ve fonksiyon içinde global bildirimine gerek duymazlar. Kılavuzun listesi şöyledir:

Değişkenİçerik
$GLOBALSGlobal kapsamdaki tüm değişkenler
$_SERVERSunucu ve çalışma ortamı bilgileri
$_GETURL sorgu dizesindeki parametreler
$_POSTPOST ile gönderilen form verileri
$_FILESYüklenen dosyalar
$_COOKIEÇerezler
$_SESSIONOturum değişkenleri
$_REQUESTGET, POST ve çerez verilerinin birleşimi
$_ENVOrtam değişkenleri

Tarayıcıdan gelen $_GET, $_POST ve $_COOKIE değerleri her zaman kullanıcı kontrolündedir; doğrulamadan kullanılmamalıdır. Doğrulama ve çıktı kaçırma filter_var yazısında, komut satırında betiğe verilen argümanları tutan $argv ve $argc ise PHP CLI yazısında anlatılıyor. Dosya yükleme sınırları gibi sunucu ayarları için upload_max_filesize yazısına bakabilirsiniz.

Sık yapılan hatalar

  • Fonksiyon içinden global değişkeni doğrudan okumak: PHP'de global değişkenler fonksiyon içinde kendiliğinden görünmez; parametre geçirin ya da global kullanın.
  • Tanımsız değişkenin null olmasına güvenmek: Uyarı üretir ve include edilen dosyalarla çakışabilir. Değişkenleri kullanmadan önce başlatın.
  • Ad büyük-küçük harfini karıştırmak: $Ad ile $ad iki farklı değişkendir.
  • $GLOBALS kopyasını değiştirip global değeri değiştirdiğini sanmak: PHP 8.1'den beri kopya bağımsızdır.
  • Closure içinde use unutmak: Klasik anonim fonksiyon dış değişkeni görmez; use ekleyin veya arrow function kullanın.

Sık Sorulan Sorular

PHP'de değişken tanımlamak için bir anahtar kelime var mı?

Hayır. JavaScript'teki let veya var gibi bir bildirim anahtar kelimesi yoktur; ilk atama değişkeni oluşturur. Tip de atanan değerden belirlenir. Fonksiyon parametreleri ve sınıf özellikleri için tip bildirebilirsiniz; bu konu tip bildirimleri yazısında işleniyor.

Türkçe karakterli değişken adı kullanmak doğru mu?

Dil açısından geçerlidir, çünkü UTF-8 baytları izin verilen aralıktadır. Ancak adlar bayt olarak karşılaştırıldığı için aynı görünen farklı yazımlar ayrı değişken sayılır. Bu yüzden kod tabanında ASCII adlar tercih etmek daha güvenlidir.

unset() ile null atamak arasında fark var mı?

Her ikisinde de isset() false döner ve okunan değer null olur. Fark, değişkenin var olmaya devam edip etmemesidir: null atanmış değişken tanımlıdır ve okununca uyarı vermez, unset() ile silinen değişken ise artık yoktur ve okunduğunda "Undefined variable" uyarısı üretir.

php
<?php
$a = null;
$b = 'dolu';
unset($b);

var_dump(isset($a), isset($b));
var_dump($a);
var_dump($b);
text
bool(false)
bool(false)
NULL

Warning: Undefined variable $b in /yol/ornek.php on line 8
NULL

global ile $GLOBALS arasında fark var mı?

global $x fonksiyon içinde global değişkene bağlı yerel bir referans oluşturur; sonrasında $x diye kullanırsınız. $GLOBALS['x'] ise her seferinde diziye anahtarla erişir ve ek bildirim gerektirmez. İkisi de aynı global değeri okur ve tek bir anahtara yazarak değiştirir.

static değişken ile sınıfın static özelliği aynı şey mi?

Hayır. static değişken bir fonksiyona veya metoda yereldir ve yalnızca orada görünür. Sınıfın statik özelliği ise sınıfa aittir ve Sinif::$ozellik biçiminde dışarıdan da erişilebilir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: PHP öğrenme rehberi · PHP temel sözdizimi · PHP sabitler · PHP veri tipleri · PHP referanslar · Undefined variable uyarısı