Ders 04 / 14
İşleçler
PHP işleçlerinin iki tipi buluşturduğunda ne söylediği: sayısal dizgilerle aritmetik, gevşek ve katı eşitlik, birleştirme ve öncelik, sıfıra bölme ve boş değer birleştirme işlecinin uyarıyı susturması.
Yayın Güncelleme
Bu derste
- Sayısal dizgilerle aritmetiğin sonucunu ve bildirdiği seviyeyi ölçerek ayırt eder
- Gevşek ve katı eşitliğin aynı çift için ürettiği farklı sonuçları tabloyla gösterir
- Birleştirme, toplama ve mantıksal işleçlerin öncelik sırasının sonucu nasıl değiştirdiğini doğrular
- Boş değer birleştirme işlecinin uyarıyı susturduğunu ve bunun neyi gizlediğini ölçer
İçindekiler
Değişkenler ve Veri Tipleri dersi, bir değerin tipinin atamada, bölmede ve dönüşümde sinyal vermeden değişebildiğini ölçtü. Bu ders aynı soruyu işleçlere soruyor: bir işleç iki farklı tipi buluşturduğunda, ya da işleneni işleç için uygun olmadığında, dil ne söylüyor? Cevap işleçten işlece değişir ve bu dersin ölçü sınıfı uyarıdır: işlem çoğu zaman sürer, ama yanında bir bildirim taşır.
JavaScript’te aynı soru M06/K01’de ölçülmüştü: orada zorlama ve eşitlik kendi kurallarıyla işliyordu. PHP’nin kuralları ondan ayrıdır ve ölçüm yine yöntemi aynı tutar: her dosya bir hata işleyicisi kurar, işleyici bildirimin seviyesini adıyla basar ve ileti metni yazdırılmaz, çünkü ileti sürüme bağlıdır.
Sayısal Dizgilerle Aritmetik
PHP bir dizgiyi aritmetikte kullanabilir: dizgi bir sayı gibi okunuyorsa sayıya dönüştürülür. Üç durum vardır. Dizgi tamamen sayıdır, dizgi bir sayıyla başlayıp başka karakterlerle sürer, ya da dizgide hiç sayı yoktur. Aşağıdaki dosya üçünü de 1 ile toplar ve her birinin sonucunu ya da fırlattığı istisnayı basar.
<?php // aritmetik.php — sayisal dizgi: tam sayi sessiz, onek uyari, sayi olmayan TypeError set_error_handler(function (int $seviye): bool { echo 'bildirilen: ', $seviye === E_WARNING ? 'E_WARNING' : 'baska', "\n"; return true; }); foreach (['5', '5 elma', 'elma'] as $girdi) { try { $sonuc = $girdi + 1; echo var_export($girdi, true), ' + 1 = ', var_export($sonuc, true), "\n"; } catch (TypeError $hata) { echo var_export($girdi, true), ' + 1 -> ', get_class($hata), "\n"; } }
'5' + 1 = 6 bildirilen: E_WARNING '5 elma' + 1 = 6 'elma' + 1 -> TypeError
KN26. Üç girdi üç ayrı sonuç verdi. Tamamen sayısal dizgi sessizce sayıya çevrildi. Sayıyla başlayan dizgi sayı önekiyle işlendi ve bir E_WARNING bildirdi; işlem yine de bitti. Hiç sayı taşımayan dizgi ise toplamayı yapmadan bir TypeError fırlattı. Bu ders sınıfın adını uyarı koyar, çünkü ortadaki durum hem sonuç üretir hem de bildirim taşır; ama üç durum, tek işleçte üç farklı sınıfı yan yana gösterir.
Gevşek ve Katı Eşitlik
== iki değeri karşılaştırmadan önce ortak bir tipe getirmeye çalışır; === hem tipe hem değere bakar. İkisi aynı çift için farklı cevap verebilir ve sinyal hiç gelmez. Aşağıdaki dosya sekiz çifti iki işleçle karşılaştırır. Çiftler, yaygın yanlış anlamaların çoğunu kapsayacak biçimde seçildi: sayısal dizgiler, boş dizgiyle null, sıfırla dizgi, boş diziyle false.
<?php // esitlik.php — gevsek ve kati esitlik ayni cift icin ayri cevap verir $cift = [ ["'1e3' ve '1000'", '1e3', '1000'], ["'abc' ve 0", 'abc', 0], ["'0' ve false", '0', false], ["'' ve null", '', null], ["'1' ve '01'", '1', '01'], ["100 ve '1e2'", 100, '1e2'], ['[] ve false', [], false], ['null ve 0', null, 0], ]; printf("%-18s%-7s%s\n", 'cift', '==', '==='); foreach ($cift as [$ad, $a, $b]) { printf("%-18s%-7s%s\n", $ad, var_export($a == $b, true), var_export($a === $b, true)); }
cift == === '1e3' ve '1000' true false 'abc' ve 0 false false '0' ve false true false '' ve null true false '1' ve '01' true false 100 ve '1e2' true false [] ve false true false null ve 0 true false
KN27. '1e3' == '1000' doğru çıktı: iki dizgi de sayısal olduğu için sayı olarak karşılaştırıldı ve 1e3 bin demektir. 'abc' == 0 yanlış çıktı: sayısal olmayan bir dizgi, sayıyla karşılaştırılırken 0 ile eşit sayılmıyor. '0' == false, '' == null, [] == false ve null == 0 doğru çıktı. Katı eşitlik sekiz çiftin hiçbirinde doğru vermedi, çünkü sekizinde de tipler ayrıdır. Bu tablo, ==’in bir sinyali olmadığını ama sonucunun değerin biçimine bağlı olduğunu gösterir.
Karşılaştırma, Birleştirme ve Öncelik
<=> işleci (uzay gemisi işleci, spaceship operator) iki değeri karşılaştırıp -1, 0 ya da 1 verir. . işleci dizgi birleştirir. and ve && aynı mantığı farklı öncelikle yapar. Aşağıdaki dosya dört ifadeyi çalıştırır: sayısal dizgiler <=> ile, sayısal olmayan bir dizgi <=> ile, + ile . karışımı ve and ile atama.
<?php // oncelik.php — karsilastirma ve oncelik sonucu degistirir echo "'10' <=> '9': ", '10' <=> '9', "\n"; echo "'10' <=> '9a': ", '10' <=> '9a', "\n"; echo "1 + 2 . '3': ", 1 + 2 . '3', "\n"; echo "'1' . 2 + 3: ", '1' . 2 + 3, "\n"; $a = true and false; $b = (true and false); echo 'a: ', var_export($a, true), ' b: ', var_export($b, true), "\n";
'10' <=> '9': 1 '10' <=> '9a': -1 1 + 2 . '3': 33 '1' . 2 + 3: 15 a: true b: false
KN28. İki sayısal dizge sayı olarak karşılaştırıldı: '10' büyüktür '9'. '9a' sayısal olmadığı için karşılaştırma dizgi olarak yapıldı ve '10' küçük çıktı. + ile . karışımında toplama önce yapıldı: 1 + 2 . '3' ifadesi '33', '1' . 2 + 3 ifadesi '15' verdi. Son iki satır en sinsi olandır: and atamadan sonra işlendiği için $a = true and false ifadesinde $a doğru kaldı, parantezli $b ise yanlış oldu. Hiçbiri bildirim üretmedi.
Artırma ve Azaltma
++ ve -- işleçleri sayılarda beklenen işi yapar, ama operand bir dizgi ya da null olduğunda davranışları ayrışır. Dizgiler Perl’deki gibi alfabetik olarak artırılır; null artırılınca 1 olur, azaltılınca null kalır. Aşağıdaki dosya altı durumu çalıştırır, sonucu ve tipini basar ve işleyici bir sayaç tutar.
<?php // artirma.php — ++ ve -- dizgi ve null uzerinde ayri davranir set_error_handler(function (int $seviye): bool { echo $seviye === E_DEPRECATED ? " [E_DEPRECATED]\n" : ($seviye === E_WARNING ? " [E_WARNING]\n" : " [baska]\n"); return true; }); $durumlar = ['5', 'a', 'z', 'Az', 'a9', '']; foreach ($durumlar as $baslangic) { $x = $baslangic; $x++; printf("%-6s++ -> %-7s%s\n", var_export($baslangic, true), var_export($x, true), get_debug_type($x)); } $bos = null; $bos++; $yok = null; $yok--; echo 'null++ -> ', var_export($bos, true), ' null-- -> ', var_export($yok, true), "\n";
'5' ++ -> 6 int [E_DEPRECATED] 'a' ++ -> 'b' string [E_DEPRECATED] 'z' ++ -> 'aa' string [E_DEPRECATED] 'Az' ++ -> 'Ba' string [E_DEPRECATED] 'a9' ++ -> 'b0' string [E_DEPRECATED] '' ++ -> '1' string [E_WARNING] null++ -> 1 null-- -> NULL
KN29. '5' artırılınca bir tam sayı oldu ve sessiz kaldı. 'a' 'b' oldu, 'z' 'aa', 'Az' 'Ba', 'a9' 'b0': sayısal olmayan dizgilerde artırma alfabetik bir kuraldır ve beş dizginin hepsi bir E_DEPRECATED bildirdi; bu bildirim PHP 8.5 ile sayısal olmayan bütün dizgilere yayıldı. null artırılınca 1 verdi ve sessiz kaldı; azaltılınca null kaldı ve bir E_WARNING bildirdi. Aynı işleç, operandın tipine göre sessiz, kullanımdan kalkmış ya da uyarılı bir sonuç verdi.
Kalan ve Üs
% işleci kalanı verir ama işareti bölünenin işaretidir; operandlar tam sayıya çevrilir ve kesir atılır. ** işleci üs alır ve sonuç int sınırını aşarsa float olur. Aşağıdaki dosya beş ifadeyi basar.
<?php // kalan.php — % isareti bolunenden alir, ** tasarsa float olur $bildirim = 0; set_error_handler(function (int $seviye) use (&$bildirim): bool { $bildirim++; return true; }); $ifadeler = [ '-7 % 3' => -7 % 3, '7 % -3' => 7 % -3, '7.9 % 3' => 7.9 % 3, '2 ** 10' => 2 ** 10, '2 ** -1' => 2 ** -1, ]; foreach ($ifadeler as $ifade => $sonuc) { printf("%-10s%-6s%s\n", $ifade, get_debug_type($sonuc), var_export($sonuc, true)); } echo '2 ** 200: ', get_debug_type(2 ** 200), "\n"; echo 'bildirim: ', $bildirim, "\n";
-7 % 3 int -1 7 % -3 int 1 7.9 % 3 int 1 2 ** 10 int 1024 2 ** -1 float 0.5 2 ** 200: float bildirim: 1
KN30. -7 % 3 ifadesi -1, 7 % -3 ifadesi 1 verdi: işaret bölünenden gelir. 7.9 % 3 ifadesinde 7.9 önce 7’ye kesildi, sonuç 1 oldu ve bir bildirim sayıldı; kesirli sayının tam sayıya örtük çevrilmesi kayıp uyarısı verir. 2 ** 10 bir int, 2 ** -1 bir float; 2 ** 200 taşınca float oldu ve tip bildirim taşımadan değişti. Son satır bu dersin Değişkenler dersiyle buluştuğu yerdir: tam sayı sınırının aşılması burada da sessizdir.
Birleşik Atama İşleçleri
+=, .= ve ??= gibi birleşik atama işleçleri, değişkeni okuyup yeniden yazar. Değişken tanımsızsa okuma kısmı uyarı üretir; ??= ise okumayı güvenli yapar ve yalnız değer yoksa atar. Aşağıdaki dosya tanımsız bir sayaca ve tanımsız bir dizgiye ekleme yapar, sonra aynı işi ??= ile yapar. İşleyici seviye adını basar; kaçıncı bildirimin hangi satırdan geldiği çıktıdaki sırayla okunur.
<?php // birlesik.php — += ve .= tanimsizi okurken uyarir, ??= uyarmaz set_error_handler(function (int $seviye): bool { echo $seviye === E_WARNING ? " [E_WARNING]\n" : " [baska]\n"; return true; }); echo "+= tanimsiz:\n"; $sayac += 5; echo ' sayac: ', var_export($sayac, true), "\n"; echo ".= tanimsiz:\n"; $yazi .= 'a'; echo ' yazi: ', var_export($yazi, true), "\n"; echo "??= tanimsiz:\n"; $sure ??= 30; echo ' sure: ', var_export($sure, true), "\n"; echo "??= tanimli:\n"; $sure ??= 99; echo ' sure: ', var_export($sure, true), "\n";
+= tanimsiz: [E_WARNING] sayac: 5 .= tanimsiz: [E_WARNING] yazi: 'a' ??= tanimsiz: sure: 30 ??= tanimli: sure: 30
KN31. += ve .= tanımsız değişkeni okurken birer E_WARNING bildirdi, ama işlem sürdü: sayaç 5, dizgi 'a' oldu. ??= ilk çağrıda değişkeni atadı ve bildirim üretmedi; ikinci çağrıda değişken tanımlı olduğu için hiçbir şey yapmadı ve 30 kaldı. Uyarıdan kaçınmanın dürüst yolu budur: değişkenin yokluğunu bir karar olarak ifade etmek, uyarıyı susturmak yerine ihtiyacı adlandırır.
Sıfıra Bölme
Sıfıra bölme, bu dersin ilk durdurur davranışıdır. / ve % işleçleri ile intdiv() sıfıra bölünce bir DivisionByZeroError fırlatır; fdiv() ise işlemi hatasız yapar ve kayan noktalı sonsuzluk verir. Aşağıdaki dosya dört çağrıyı sınar. Sonuç hesaplanıp ayrıca yazdırılır, çünkü virgüllü bir echo işlemin ortasında kesilirse kısmi çıktı bırakır.
<?php // sifir.php — sifira bolme durdurur, fdiv sonsuzluk verir $sifir = 0; $cagrilar = [ '1 / 0' => fn() => 1 / $sifir, '1 % 0' => fn() => 1 % $sifir, 'intdiv(1, 0)' => fn() => intdiv(1, $sifir), 'fdiv(1, 0)' => fn() => fdiv(1, $sifir), ]; foreach ($cagrilar as $ad => $cagri) { try { $sonuc = $cagri(); $yazi = var_export($sonuc, true); } catch (DivisionByZeroError $hata) { $yazi = get_class($hata); } printf("%-14s%s\n", $ad, $yazi); }
1 / 0 DivisionByZeroError 1 % 0 DivisionByZeroError intdiv(1, 0) DivisionByZeroError fdiv(1, 0) INF
KN32. Üç işlem DivisionByZeroError fırlattı, fdiv() ise INF döndü. Bu, ölçü sınıfının sınırını gösterir: dil uyarıyla yetinmeyen bir hata türüne sahip. Hata yakalanmazsa yürütme Sözdizim ve Etiketler dersindeki gibi kesilir; yakalanırsa program sürer. Sonsuzluğun kendisi ise sessiz bir değerdir ve sonraki işlemlerde NAN’a dönüşebilir.
Sınırlayıcı Ölçüm
Bu dersteki bildirimlerin hepsini susturabilen bir işleç vardır: boş değer birleştirme işleci ??. Tanımsız bir dizi anahtarını ya da değişkeni okurken uyarı bildirilir; aynı okuma ?? ile yapılırsa bildirim hiç üretilmez ve bu bilgi kaybolur. Aşağıdaki dosya aynı eksik anahtarı üç yoldan okur ve hata işleyicisi her bildirimi sayar.
<?php // susturma.php — ?? uyariyi susturur ve eksik anahtari gizler $bildirim = 0; set_error_handler(function (int $seviye) use (&$bildirim): bool { $bildirim++; return true; }); $ayarlar = ['sure' => 30]; $a = $ayarlar['sur']; echo 'dogrudan okuma: ', var_export($a, true), ' bildirim: ', $bildirim, "\n"; $b = $ayarlar['sur'] ?? 0; echo '?? ile okuma: ', var_export($b, true), ' bildirim: ', $bildirim, "\n"; $c = $ayarlar['sure'] ?? 0; echo 'dogru anahtar: ', var_export($c, true), ' bildirim: ', $bildirim, "\n";
dogrudan okuma: NULL bildirim: 1 ?? ile okuma: 0 bildirim: 1 dogru anahtar: 30 bildirim: 1
KN33. Doğrudan okuma null verdi ve bir bildirim üretti. Yazım hatalı anahtarın ?? ile okunması bildirim üretmedi ve 0 döndü: yazım hatası, geçerli bir varsayılan değer gibi görünür hâle geldi. Üçüncü okuma doğru anahtarı buldu ve 30 verdi; sayaç yine bir kaldı. Bu bir hata değil, ölçümün sınırıdır: ?? uyarıyı susturur, dolayısıyla uyarı sınıfı bir işlecin arkasında sessiz sınıfa dönüşür. Varsayılan değer istenen davranışsa ?? doğrudur; yazım hatasını yakalamak istenen davranışsa, kullanılmamalıdır.
Özet
- İşleçlerin ölçü sınıfı uyarıdır: sayıyla başlayan dizgi
E_WARNINGbildirir ve işlem sürer; tamamen sayısal dizgi sessizdir; sayı olmayan dizgiTypeErrorfırlatır. ==iki değeri ortak bir tipe getirerek karşılaştırır,===tipi de arar; sekiz çiftin hiçbirinde ikisi birden doğru çıkmadı ve hiçbir karşılaştırma bildirim üretmedi.+,.işlecinden önce işlenir veandatamadan sonra çalışır;$a = true and falseifadesi$a’ya doğru atar./,%veintdiv()sıfıra bölünceDivisionByZeroErrorfırlatır;fdiv()INFdöndürür.??tanımsız anahtar ve değişken uyarısını susturur; yazım hatası böylece sessiz bir varsayılana dönüşür.
Sonraki Adım
İşleçlerin tipleri buluşturduğunda neyi bildirdiği ve neyi susturduğu görüldü. Denetim Akışı dersi aynı soruyu dallara soruyor: bir koşulun hiçbir kolu eşleşmediğinde, yani karşılıksız bir dal kaldığında dil ne yapıyor?
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.