PHP operatörleri bir veya daha fazla değer alıp yeni bir değer üreten işaretlerdir. Günlük kodda en çok kullanılanlar aritmetik (+ - * / % **), atama (= += .= ??=), karşılaştırma (== === <=>), mantıksal (&& || !), metin birleştirme (.) ve null birleştirme (??) operatörleridir. Bir ifadede birden fazla operatör olduğunda hangisinin önce uygulanacağını öncelik (precedence) tablosu, aynı öncelikteki operatörlerin nasıl gruplanacağını ise birleşme yönü (associativity) belirler.
Bu yazıda operatör gruplarını tek tek, PHP 8.5.12 ile çalıştırılmış örneklerle anlatıyor ve en sık hata yapılan öncelik durumlarını gösteriyoruz. == ile === arasındaki farkın ve tip dönüşümünün ayrıntıları eşitlik ve karşılaştırma yazısının konusu; burada yalnızca özetliyoruz. Serinin tamamı PHP öğrenme rehberi sayfasında.
Aritmetik operatörler
Toplama, çıkarma, çarpma, bölme, mod (kalan) ve üs alma operatörleri okuldaki aritmetikle aynı şekilde çalışır. Birkaç ayrıntı yine de bilinmelidir. Bölme operatörü /, iki işlenen de tamsayıysa ve bölünen bölenin tam katıysa int, diğer tüm durumlarda float döndürür. Mod operatörü % işlenenleri önce tamsayıya çevirir ve sonucun işareti her zaman bölünenin işaretiyle aynıdır; ondalıklı sayılarda kalan için fmod() kullanılır. Üs alma operatörü ** negatif üslerde ondalıklı sonuç verir.
<?php
var_dump(10 + 3); // çıktı: int(13)
var_dump(10 / 4); // çıktı: float(2.5)
var_dump(10 / 5); // çıktı: int(2)
var_dump(10 % 3); // çıktı: int(1)
var_dump(-10 % 3); // çıktı: int(-1)
var_dump(10 % -3); // çıktı: int(1)
var_dump(2 ** 10); // çıktı: int(1024)
var_dump(2 ** -1); // çıktı: float(0.5)
var_dump(fmod(7.5, 2)); // çıktı: float(1.5)
Tekli + ve - de birer operatördür: -$a değerin işaretini değiştirir, +$a ise değeri uygun sayı tipine çevirir. Tamsayı bölümü için ayrı bir operatör yoktur; intdiv() fonksiyonunu kullanırsınız. Sıfıra bölme ve sayı sınırlarıyla ilgili hatalar TypeError ve DivisionByZeroError yazısında ele alınıyor.
Atama ve birleşik atama operatörleri

Kılavuz, = işaretini "eşittir" diye okumamanızı özellikle vurgular: anlamı "sağdaki ifadenin değeri soldaki değişkene konur" demektir. Atama işlemi bir ifadedir ve değeri atanan değerdir. Bu sayede $a = ($b = 4) + 5 gibi iç içe atamalar mümkündür. Atama sağdan sola birleşir; $a = $b = 0 yazımı önce $b'ye, sonra $a'ya sıfır atar.
Her ikili aritmetik operatörün, metin birleştirmenin ve dizi birleşiminin bir birleşik atama hâli vardır: $a += 5 ifadesi $a = $a + 5 ile aynıdır. ??= ise yalnızca sol taraf tanımsız veya null ise atama yapar; varsayılan ayarları doldurmak için idealdir.
<?php
$toplam = 100;
$toplam += 20; // 120
$toplam *= 2; // 240
$toplam -= 40; // 200
$toplam /= 4; // 50
var_dump($toplam); // çıktı: int(50)
$metin = 'Merhaba';
$metin .= ' dünya';
var_dump($metin); // çıktı: string(14) "Merhaba dünya"
$a = ($b = 4) + 5;
var_dump($a, $b);
/* çıktı:
int(9)
int(4)
*/
$ayarlar = ['dil' => 'tr'];
$ayarlar['dil'] ??= 'en'; // zaten var, değişmez
$ayarlar['tema'] ??= 'koyu'; // yoksa atanır
print_r($ayarlar);
/* çıktı:
Array
(
[dil] => tr
[tema] => koyu
)
*/
| Operatör | Eşdeğeri | İşlem |
|---|---|---|
| $a += $b | $a = $a + $b | Toplama |
| $a -= $b | $a = $a - $b | Çıkarma |
| $a *= $b | $a = $a * $b | Çarpma |
| $a /= $b | $a = $a / $b | Bölme |
| $a %= $b | $a = $a % $b | Mod |
| $a **= $b | $a = $a ** $b | Üs alma |
| $a .= $b | $a = $a . $b | Metin birleştirme |
| $a ??= $b | $a = $a ?? $b | Null birleştirme |
Atama değerle yapılır, yani sağdaki değer kopyalanır. Nesneler bu kuralın görünürdeki istisnasıdır: nesneyi başka bir değişkene atadığınızda iki değişken aynı nesneyi gösterir. Referansla atama ($b = &$a) ise referanslar yazısında anlatılıyor.
Artırma ve azaltma: ++ ve --
++$a önce değeri bir artırıp sonra döndürür; $a++ ise önce mevcut değeri döndürür, ardından artırır. Aynı ayrım -- için de geçerlidir. Döngü sayaçlarında fark etmez, ama bir ifadenin içinde kullanıldığında sonucu değiştirir.
Bu operatörlerin tamsayı dışındaki tiplerde davranışı tutarsızdır ve son sürümlerde uyarılarla sıkılaştırılıyor. Kılavuza göre bool değerlerde ikisinin de etkisi yoktur ve PHP 8.3'ten beri uyarı verilir. null artırıldığında 1 olur, ama azaltıldığında değişmez ve yine 8.3'ten beri uyarı üretir. Sayısal olmayan metinlerin harf harf artırılması ('Az' değerinden 'Ba' değerine) PHP 8.3'te yumuşak biçimde kullanımdan kaldırıldı; PHP 8.5'ten beri tüm sayısal olmayan metinler için deprecated bildirimi verir. Bunun yerine PHP 8.3 ile gelen str_increment() fonksiyonunu kullanın.
<?php
$a = 5;
var_dump($a++); // çıktı: int(5)
var_dump($a); // çıktı: int(6)
var_dump(++$a); // çıktı: int(7)
var_dump($a--); // çıktı: int(7)
var_dump(--$a); // çıktı: int(5)
$n = null;
$n++;
var_dump($n); // çıktı: int(1)
$m = null;
$m--;
var_dump($m);
int(5)
int(6)
int(7)
int(7)
int(5)
int(1)
Warning: Decrement on type null has no effect, this will change in the next major version of PHP in /yol/ornek.php on line 14
NULL<?php
$s = 'Az';
$s++;
var_dump($s);
var_dump(str_increment('Az'));
Deprecated: Increment on non-numeric string is deprecated, use str_increment() instead in /yol/ornek.php on line 3
string(2) "Ba"
string(2) "Ba"Metin birleştirme: nokta operatörü

PHP'de metinler + ile değil nokta (.) ile birleştirilir; .= ise sağdaki metni soldakinin sonuna ekler. + operatörünü iki metinle kullanırsanız PHP onları sayıya çevirmeye çalışır ve sayısal değillerse TypeError alırsınız. Bu, JavaScript'ten gelenlerin en sık yaptığı hatalardan biridir.
PHP 8.0 ile noktanın önceliği değişti. Önceden nokta, toplama ve çıkarmayla aynı öncelikteydi ve soldan sağa işleniyordu; "x eksi bir: " . $x - 1 ifadesi önce metni birleştirip sonra 1 çıkarmaya çalışıyordu. PHP 8'de nokta, + ve - operatörlerinden daha düşük önceliğe sahiptir, bu yüzden aritmetik önce yapılır:
<?php
$x = 4;
echo 'x eksi bir: ' . $x - 1, "\n"; // çıktı: x eksi bir: 3
echo 'x eksi bir: ' . ($x - 1), "\n"; // çıktı: x eksi bir: 3
$e = false || true; // ($e = (false || true))
$f = false or true; // (($f = false) or true)
var_dump($e, $f);
/* çıktı:
bool(true)
bool(false)
*/
Örneğin ikinci yarısı ayrı bir tuzağı gösteriyor: or, and ve xor kelime operatörleri atamadan daha düşük önceliğe sahiptir. $f = false or true satırı önce $f'ye false atar, sonra sonucu kullanılmayan bir or işlemi yapar.
Mantıksal operatörler
PHP'de "ve" ile "veya" için iki ayrı yazım vardır: sembol olarak && ve ||, kelime olarak and ve or. Kılavuza göre tek fark önceliktir; sembol hâlleri atamadan önce, kelime hâlleri atamadan sonra uygulanır. Kafa karışıklığını önlemek için ifadelerde sembol hâllerini kullanmak yaygın bir tercihtir. xor, iki işlenenden yalnızca biri doğruysa true döner; ! değeri tersine çevirir.
&&, ||, and ve or kısa devre (short-circuit) değerlendirme yapar: sonuç sol tarafa bakarak belli oluyorsa sağ taraf hiç çalıştırılmaz. false && kaydet() ifadesinde kaydet() çağrılmaz. Bu davranış, $kullanici !== null && $kullanici->aktifMi() gibi koruyucu kontroller için kullanılır.
Karşılaştırma operatörleri ve uzay gemisi <=>
== tip dönüşümünden sonra değerleri karşılaştırır, === ise hem değerin hem tipin aynı olmasını ister. != (veya <>) ve !== bunların tersidir; <, >, <= ve >= büyüklük karşılaştırması yapar. Uzay gemisi operatörü <=> ise sol taraf küçükse sıfırdan küçük, eşitse 0, büyükse sıfırdan büyük bir tamsayı döndürür. PHP 8.5.12'de bu değerler -1, 0 ve 1 olarak geldi, ancak kılavuz yalnızca işaretin garanti olduğunu söyler; kodunuzda === -1 yerine < 0 kontrolü yapın.
<?php
var_dump(1 <=> 2); // çıktı: int(-1)
var_dump(2 <=> 2); // çıktı: int(0)
var_dump(3 <=> 2); // çıktı: int(1)
var_dump('a' <=> 'b'); // çıktı: int(-1)
var_dump([1, 2] <=> [1, 3]); // çıktı: int(-1)
$varsayilan = ['dil' => 'tr', 'tema' => 'acik'];
$kullanici = ['tema' => 'koyu'];
print_r($kullanici + $varsayilan);
/* çıktı:
Array
(
[tema] => koyu
[dil] => tr
)
*/
<=> özellikle usort() için karşılaştırma fonksiyonu yazarken kullanışlıdır; dizi sıralama yazısında örneklerini görebilirsiniz. Örneğin son kısmı dizi birleşim operatörünü gösteriyor: $a + $b, iki dizide de bulunan anahtarlarda soldaki dizinin değerini korur ve yalnızca soldakinde olmayan anahtarları sağdan ekler. Bu yüzden kullanıcı ayarlarını varsayılanlarla tamamlamak için idealdir; array_merge() ile karıştırılmamalıdır.
Üçlü operatör, kısa üçlü ve null birleştirme
koşul ? a : b biçimindeki üçlü operatör, koşul doğruysa a, değilse b ifadesinin değerini verir. Ortadaki kısım atlanarak yazılan kısa üçlü a ?: b, a doğru sayılan bir değerse onu, aksi hâlde b'yi döndürür. Null birleştirme operatörü a ?? b ise yalnızca a tanımsız veya null olduğunda b'ye geçer ve isset() gibi tanımsız değişken veya dizi anahtarı için uyarı vermez.
?: ile ?? arasındaki fark sıfır, boş metin ve false gibi değerlerde ortaya çıkar. Aşağıdaki örnekte stok 0 olduğunda ?: "tükendi" yazar, çünkü 0 yanlış sayılır; ?? ise 0 değerini olduğu gibi döndürür, çünkü 0 null değildir.
<?php
$stok = 0;
echo $stok ?: 'tükendi', "\n"; // çıktı: tükendi
echo $stok ?? 'tükendi', "\n"; // çıktı: 0
$kullanici = ['ad' => null];
echo $kullanici['ad'] ?? 'Misafir', "\n"; // çıktı: Misafir
echo $kullanici['soyad'] ?? 'yok', "\n"; // çıktı: yok
echo $a ?? $b ?? 'üçüncü', "\n"; // çıktı: üçüncü
$puan = 72;
echo $puan >= 50 ? 'geçti' : 'kaldı', "\n"; // çıktı: geçti
echo 'Sayın ' . ($ad ?? 'Ziyaretçi'), "\n"; // çıktı: Sayın Ziyaretçi
?? düşük önceliklidir. 'Sayın ' . $ad ?? 'Ziyaretçi' yazarsanız önce birleştirme yapılır; $ad tanımsız olduğu için uyarı alırsınız ve varsayılan değer hiç devreye girmez. Örnekteki gibi parantez kullanın.
İç içe üçlü operatör PHP 8'de hata verir
PHP 8.0'dan önce üçlü operatör soldan sağa birleşiyordu ve iç içe yazıldığında diğer dillerden farklı sonuç veriyordu. PHP 8'de üçlü operatör birleşmesiz (non-associative) hâle geldi; parantezsiz iç içe kullanım derleme hatasıdır. Kısa üçlünün zincirlenmesi (0 ?: 0 ?: 3) ise bu kuralın dışındadır ve ilk doğru değeri verir.
<?php
echo true ? 'a' : false ? 'b' : 'c';
Fatal error: Unparenthesized `a ? b : c ? d : e` is not supported. Use either `(a ? b : c) ? d : e` or `a ? b : (c ? d : e)` in /yol/ornek.php on line 2
Stack trace:
#0 {main}Mesajın altındaki "Stack trace" satırı da bir sürüm ayrıntısı: PHP 8.5 ile ölümcül hatalar artık bir geri izleme (backtrace) içeriyor.
Pipe operatörü |> (PHP 8.5)
PHP 8.5 ile gelen |> operatörü, solundaki değeri sağındaki tek parametreli callable'a verir ve sonucunu döndürür. $x |> strlen(...) ifadesi strlen($x) ile aynıdır. Asıl faydası zincirleme kullanımdadır: iç içe fonksiyon çağrılarını veya ara değişkenleri soldan sağa okunan bir akışa çevirir. Sağ taraf birinci sınıf callable, closure veya __invoke() metodu olan bir nesne olabilir; kılavuza göre arrow function kullanılıyorsa sözdizimi belirsizliğini önlemek için parantez içine alınması zorunludur. Birden fazla zorunlu parametre alan veya parametreyi referansla alan fonksiyonlar sağ tarafta kullanılamaz. Bu özellik PHP 8.5 veya sonrasını gerektirir.
<?php
$sonuc = ' Merhaba Dünya '
|> trim(...)
|> mb_strtoupper(...)
|> (fn($s) => str_replace(' ', '-', $s));
var_dump($sonuc); // çıktı: string(14) "MERHABA-DÜNYA"
Pipe operatörünün öncelik tablosundaki yeri birleştirme ile karşılaştırma operatörleri arasındadır. Daha fazla örnek ve 8.4 ile karşılaştırma PHP 8.5 yenilikleri yazısında, birinci sınıf callable sözdizimi ise anonim fonksiyon yazısında anlatılıyor.
Diğer operatörler

- instanceof: Bir değerin belirli bir sınıfın veya arayüzün örneği olup olmadığını kontrol eder. Kalıtım ve arayüzlerle ilişkisi kalıtım yazısında anlatılıyor.
- @ (hata bastırma): Önüne konduğu ifadenin ürettiği uyarıları gizler. Hataları gizlemek yerine ele almak daha doğrudur; error_reporting yazısına bakın.
- Bit düzeyi operatörler:
&,|,^,~,<<ve>>tamsayıların bitleri üzerinde çalışır; hata seviyesi maskeleri gibi yerlerde görülür. - Ters tırnak (backtick): Kabuk komutu çalıştıran bu operatör PHP 8.5'te kullanımdan kaldırıldı; gerekiyorsa
shell_exec()kullanın.
Operatör önceliği tablosu
Aşağıdaki tablo, kılavuzdaki öncelik listesinin günlük kodda en çok karşılaşılan satırlarını yukarıdan aşağıya azalan öncelik sırasıyla gösterir. Aynı satırdaki operatörler eşit önceliğe sahiptir ve birleşme yönüne göre gruplanır.
| Birleşme | Operatörler | Grup |
|---|---|---|
| yok | clone new | Nesne |
| sağ | ** | Üs alma |
| yok | + - (tekli) ++ -- ~ (int) (string) vb. @ | Tekli, dönüşüm |
| sol | instanceof | Tip |
| yok | ! | Mantıksal değil |
| sol | * / % | Aritmetik |
| sol | + - | Aritmetik |
| sol | << >> | Bit kaydırma |
| sol | . | Metin (PHP 8.0 ve sonrası) |
| sol | |> | Pipe (PHP 8.5) |
| birleşmesiz | < <= > >= | Karşılaştırma |
| birleşmesiz | == != === !== <> <=> | Karşılaştırma |
| sol | && | Mantıksal ve |
| sol | || | Mantıksal veya |
| sağ | ?? | Null birleştirme |
| birleşmesiz | ? : | Üçlü |
| sağ | = += -= .= ??= vb. | Atama |
| sol | and | Mantıksal |
| sol | xor | Mantıksal |
| sol | or | Mantıksal |
Kılavuz önemli bir sınırı da hatırlatır: öncelik ve birleşme yönü yalnızca ifadenin nasıl gruplanacağını belirler, işlenenlerin hangi sırayla değerlendirileceğini değil. $a + $a++ gibi aynı değişkeni hem okuyup hem değiştiren ifadelerin sonucu PHP sürümüne veya çevredeki koda göre değişebilir; bu tür kodlardan kaçının. Gerekmese bile parantez kullanmak, okuyana gruplamayı açıkça gösterdiği için kılavuzun da önerdiği bir alışkanlıktır.
Sık yapılan hatalar
- Metinleri + ile birleştirmek: PHP'de birleştirme operatörü noktadır.
- ?: ile ?? operatörlerini karıştırmak: 0 veya boş metin geçerli bir değerse
??kullanın. - Null birleştirmeyi birleştirme içinde parantezsiz yazmak:
??düşük önceliklidir. - and/or ile atama yapmak: Atama önce yapılır;
&&ve||kullanın. - Parantezsiz iç içe üçlü operatör: PHP 8'de derleme hatasıdır.
- <=> sonucunu -1 veya 1 ile karşılaştırmak: Yalnızca işarete güvenin.
Sık Sorulan Sorular
PHP'de ?? ve ?: farkı nedir?
?? yalnızca sol taraf tanımsız veya null ise sağ tarafı döndürür ve tanımsız anahtar için uyarı vermez. ?: ise sol taraf yanlış sayılan herhangi bir değerse (0, boş metin, "0", boş dizi, false) sağ tarafı döndürür ve tanımsız değişkende uyarı verir.
&& ile and aynı şey mi?
Mantıksal sonuç aynıdır, öncelik farklıdır. && atamadan önce, and atamadan sonra değerlendirilir. $x = true and false satırında $x değeri true olur.
PHP'de tamsayı bölme operatörü var mı?
Hayır. / sonucu tam bölünmüyorsa ondalıklı sayı verir. Tamsayı bölümü için intdiv() fonksiyonunu kullanın.
Pipe operatörünü hangi sürümden itibaren kullanabilirim?
|> PHP 8.5 ile geldi. Kodunuz daha eski sürümlerde de çalışacaksa ara değişkenler veya iç içe fonksiyon çağrıları kullanın.
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 eşitlik ve karşılaştırma · PHP veri tipleri · PHP if, switch ve match · PHP 8.5 yenilikleri