---
title: 'Sözdizim ve Etiketler'
source: 'https://academia.sh/tr/kurslar/php-temelleri/sozdizim-ve-etiketler'
course: 'PHP Temelleri'
language: tr
updated: '2026-10-21T05:03:33+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Sözdizim hatalı bir dosyanın hiçbir satırı çalışmadan durduğunu çıkış koduyla ve sunucu yanıtıyla gösterir'
    - 'Yürütme sırasında fırlayan hatayı sözdizim hatasından önceki çıktının varlığıyla ayırt eder'
    - 'Açılış, kapanış ve kısa yazdırma etiketleriyle kod ile şablonu karıştırır'
    - 'Dosya sonundaki kapanış etiketinin çıktıya bayt ekleyebileceğini ölçer'
---

# Sözdizim ve Etiketler

Sözdizim hatalı bir dosyanın hiç çalışmaya başlamaması, yürütme sırasında fırlayan hatadan farkı ve PHP dosyasında kod ile şablonun etiketlerle nasıl karıştığı.

Yürütme Modeli dersi çekirdeğin tablosunda iki satırı yan yana bıraktı: `durdurulan yurutme` bir satır basıp 255 ile çıktı, `sozdizim hatasi` hiçbir satır basmadan 255 ile çıktı. İkisi de durdurur sınıfındadır, ama aynı anda söylenen iki ayrı şey vardır: biri çalışmakta olan bir yürütmenin kesilmesi, öteki yürütmenin hiç başlayamaması. Bu ders farkı ölçüyor.

Fark, PHP'nin bir dosyayı ele alış biçiminden gelir. Dosya çalıştırılmadan önce bütünüyle okunur ve dil kurallarına göre ayrıştırılır (parse). Ayrıştırma başarısız olursa dosyanın tek bir satırı bile çalışmaz. Dosyanın nerede başlayıp nerede bittiğini ise etiketler belirler: PHP yalnız açılış ve kapanış etiketlerinin arasındaki bölümü kod sayar, dışarıda kalan her şeyi olduğu gibi çıktıya yazar. Bu derste iki konu birlikte ölçülüyor, çünkü ikisi de bir dosyanın ne zaman çalışmaya başladığıyla ilgili.

## Çalışmaya Başlamayan Dosya

İki küçük dosya aynı iki satırı taşır: önce bir satır basmak, sonra bir sorun. Birincisinde sorun yürütmede çıkar: bir `RuntimeException` fırlatılır ve yakalanmaz. İkincisinde sorun dilin kendisine aykırıdır: `$x = ;` ifadesi bir değer beklerken noktalı virgülle karşılaşır. Üçüncü dosya sağlamdır ve karşılaştırma için kullanılır. Üçü de çıktı bloğu olmadan, yalnız dosya olarak verilir.

```php
<?php
// fatal.php — once bir satir basar, sonra yakalanmayan istisna firlatir
echo "once\n";
throw new RuntimeException('dur');
```

```php
<?php
// bozuk.php — sozdizim hatasi: $x = ; ifadesinde deger yok
echo "once\n";
$x = ;
```

```php
<?php
// saglam.php — sozdizimi dogru, yalnizca bir satir basar
echo "once\n";
```

Aşağıdaki betik her dosyayı ayrı bir yürütmede çalıştırır. `display_errors=0` hata metnini çıktıdan uzak tutar; geriye yalnız dosyanın bastığı satırlar ve çıkış kodu kalır. `php -l` dosyayı çalıştırmadan yalnız ayrıştırır ve çıkış kodunu verir.

```bash
# ayri.sh — ayni iki satir, iki ayri durus: yurutmede firlayan ve ayristirmada kalan
php -d display_errors=0 fatal.php; echo "fatal cikis=$?"
php -d display_errors=0 bozuk.php; echo "bozuk cikis=$?"
php -l saglam.php >/dev/null 2>&1; echo "saglam -l=$?"
php -l bozuk.php >/dev/null 2>&1; echo "bozuk -l=$?"
```

```
once
fatal cikis=255
bozuk cikis=255
saglam -l=0
bozuk -l=255
```

**KN6.** İki dosya da 255 ile çıktı, ama `fatal.php` ilk satırını basabildi, `bozuk.php` basamadı. Ölçülen şey çıktının varlığıdır, hata iletisinin metni değil: ileti sürümle değişir ve dosya yolu taşır. `php -l` sağlam dosyada 0, bozuk dosyada 255 verdi; yani ayrıştırma sonucu, dosya hiç çalıştırılmadan öğrenilebilir.

Aynı fark yerleşik sunucuda durum koduna dönüşür. `bozuk.php` istendiğinde dosya çalışmaya başlayamadığı için sunucunun elinde bir yanıt gövdesi yoktur ve durum kodu `500` olur. `fatal.php` ise önce `once` satırını basar; gövde başlamıştır, sonra gelen hata artık durum kodunu değiştiremez. Sunucu `-d display_errors=0` ile başlar ve gövdede hata metni görünmez.

```bash
# sunucu.sh — sozdizim hatali dosya 500, yurutmede firlatan dosya kismi govdeyle 200
php -S 127.0.0.1:8081 -d display_errors=0 >/dev/null 2>&1 &
pid=$!
for i in $(seq 1 50); do curl -s -o /dev/null http://127.0.0.1:8081/saglam.php && break; sleep 0.1; done
curl -s -w 'durum=%{http_code}\n' http://127.0.0.1:8081/saglam.php
curl -s -w 'durum=%{http_code}\n' http://127.0.0.1:8081/fatal.php
curl -s -w 'durum=%{http_code}\n' http://127.0.0.1:8081/bozuk.php
kill $pid
```

```
once
durum=200
once
durum=200
durum=500
```

**KN7.** Üç istek üç ayrı sonuç verdi: sağlam dosya `once` ve `200`, yürütmede hata veren dosya aynı `once` satırıyla birlikte yine `200`, sözdizim hatalı dosya gövdesiz `500`. İkinci satırın `200` olması hatanın kaybolduğu anlamına gelmez; hata, gövde başladıktan sonra geldiği için durum koduna yansımadı. Durum kodu bu yüzden bir sorunun duyulup duyulmadığının güvenilir ölçüsü değildir, yalnızca hatanın çıktıdan önce mi sonra mı geldiğini yansıtır.

## Kod ve Şablon Karışımı

Bir PHP dosyası kodu ve düz metni iç içe taşıyabilir. Açılış etiketi `<?php` kod bölümünü başlatır, kapanış etiketi `?>` bitirir; ikisinin arasındaki her şey ayrıştırılır, dışındaki her şey değiştirilmeden çıktıya gider. `<?=` ise bir değeri yazdırmak için kullanılan kısa biçimdir: `<?= $urun ?>` yazımı `<?php echo $urun; ?>` ile aynı işi görür. Böylece bir dosya hem betik hem şablon (template) olarak yazılabilir. Aşağıdaki örnek HTML listesini bir dizi üzerinde döngüyle üretir. `foreach (...):` ve `endforeach;` yazımı, süslü parantez yerine etiketler arasına yayılan bloklar için hazırlanmış biçimdir.

```php
<?php
// sablon.php — kod ve sablon karisimi, kisa yazdirma etiketiyle
$urunler = ['kalem', 'defter', 'silgi'];
?>
<ul>
<?php foreach ($urunler as $urun): ?>
  <li><?= $urun ?></li>
<?php endforeach; ?>
</ul>
```

```
<ul>
  <li>kalem</li>
  <li>defter</li>
  <li>silgi</li>
</ul>
```

**KN8.** Her `?>` etiketinden hemen sonra gelen tek bir satır sonu çıktıya yazılmaz; PHP onu kapanış etiketinin parçası sayar. Bu yüzden çıktıda kod satırlarından kalan boş satır yoktur ve üç `<li>` satırı arada boşluk olmadan alt alta dizilir. Bu davranış yalnız tek bir satır sonu için geçerlidir; etiketten sonra iki satır sonu varsa ikincisi çıktıya girer.

Bu sonuç dosyanın en sonunda önem kazanır. Yalnız PHP kodu taşıyan bir dosyada kapanış etiketi yazılmaz; açılış etiketinin kapanışı olmadan da dosya geçerlidir. Sebep ölçülebilir: kapanış etiketinden sonra gözden kaçan bir satır sonu ya da boşluk çıktıya girer. Aşağıdaki betik aynı tek satırlık programı üç biçimde yazar ve her birinin ürettiği bayt sayısını ölçer.

```bash
# kapanis.sh — dosya sonundaki kapanis etiketinden sonra kalan satir sonu bayt ekler
printf '<?php\necho "a";\n' > acik.php
printf '<?php\necho "a";\n?>\n' > kapali1.php
printf '<?php\necho "a";\n?>\n\n' > kapali2.php
for d in acik kapali1 kapali2; do
  printf '%s %s\n' "$d" "$(php $d.php | wc -c | tr -d ' ')"
done
```

```
acik 1
kapali1 1
kapali2 2
```

**KN9.** Etiketsiz dosya ve tek satır sonlu kapanışlı dosya bir bayt üretti, `echo "a"`'nın kendisi; iki satır sonlu kapanışlı dosya iki bayt üretti. Fazladan baytın zararı görünmez olmasındadır: yanıt başlıkları gönderilmeden önce çıktıya giren her bayt, başlık ayarlamayı geç bırakır. Bu yüzden dosya yalnız kod taşıyorsa son etiket yazılmaz.

## Satır Yorumu da Kapanış Etiketinde Biter

Etiketlerin ayrıştırmadan önce işlediği bir sonuç daha vardır: kapanış etiketi, bir satır yorumunun içinde de kod bölümünü bitirir. Yorumun geri kalanı dahil, etiketten sonraki her şey düz metindir; sonraki satırlar kod olmaktan çıkar. Sözdizim hatası bu durumda çıkmaz, çünkü ortada ayrıştırılacak bir kod kalmamıştır ve dosya sorunsuz biçimde çalışır.

```php
<?php
// yorum.php — satir yorumundaki kapanis etiketi kod bolumunu bitirir
echo "a\n"; // yorum ?> bu kisim metin
echo "b\n";
```

```
a
 bu kisim metin
echo "b\n";
```

**KN10.** Çıktıda `a` satırı, ardından yorumun etiketten sonraki kısmı ve en sonda `echo "b\n";` satırının kendisi, yani kaynak metni, düz metin olarak yer aldı; `b` hiç basılmadı. Hiçbir sinyal yoktu: ne uyarı ne durum kodu. Bu gözlem tablodaki sınıflardan sessiz sınıfa girer ve dersin ölçü sınıfını değiştirmez; yalnız etiketlerin ayrıştırmadan önce, yorumun anlamından bağımsız işlendiğini gösterir.

## Harf Duyarlılığı

PHP'de bir adın büyük ve küçük harfe duyarlı olup olmadığı adın türüne bağlıdır. Anahtar sözcükler ve fonksiyon adları duyarsızdır; değişken adları ve `define()` ile tanımlanan sabit adları duyarlıdır. Bir yazım hatası bu yüzden bir yerde fark edilmez, başka yerde fark edilir. Aşağıdaki dosya dört adı büyük ve küçük harf farkıyla dener; hata işleyicisi bir sayaç tutar.

```php
<?php
// harf.php — fonksiyon adi harfe duyarsiz, degisken ve sabit adi duyarli
$bildirim = 0;
set_error_handler(function (int $seviye) use (&$bildirim): bool {
    $bildirim++;
    return true;
});

$ad = 'Ada';
define('SABIT', 5);

ECHO 'anahtar sozcuk: buyuk harfle de calisti', "\n";
echo 'STRLEN:     ', STRLEN('abc'), "\n";
echo 'bildirim:   ', $bildirim, "\n";

$gorulen = $Ad;
echo 'bildirim:   ', $bildirim, ' ($Ad okununca)', "\n";
echo 'defined(sabit): ', var_export(defined('sabit'), true), "\n";
echo 'defined(SABIT): ', var_export(defined('SABIT'), true), "\n";
```

```
anahtar sozcuk: buyuk harfle de calisti
STRLEN:     3
bildirim:   0
bildirim:   1 ($Ad okununca)
defined(sabit): false
defined(SABIT): true
```

**KN11.** `ECHO` ve `STRLEN` büyük harfle yazılsa da çalıştı ve hiçbir bildirim üretmedi. `$Ad`, `$ad`'dan ayrı bir değişkendir; okunduğunda bir uyarı duyuldu ve sayaç bire çıktı. Sabit adında da `sabit` ile `SABIT` farklıdır: yalnız tam yazım bulundu. Yani aynı yazım hatası fonksiyon adında sessizdir, değişken adında uyarıdır; hatanın hangi kanaldan duyulacağına, yanlış yazılan adın türü karar verir.

## Tek Tırnak ve Çift Tırnak

PHP'de dizgi iki biçimde yazılır ve ikisi aynı değildir. Tek tırnaklı dizgide değişken ve kaçış dizisi yorumlanmaz; yalnız `\'` ve `\\` özel anlam taşır. Çift tırnaklı dizgide değişken yerine konur ve `\n` gibi kaçış dizileri çözülür. Aşağıdaki dosya aynı metni iki biçimde yazar ve uzunluklarını sayar.

```php
<?php
// dizgi.php — tek tirnak degisken ve kacis cozmez, cift tirnak cozer
$ad = 'Ada';
$tek = 'merhaba $ad\n';
$cift = "merhaba $ad\n";
$suslu = "merhaba {$ad}x";

echo 'tek:   ', $tek, "|\n";
echo 'cift:  ', $cift, "|\n";
echo 'suslu: ', $suslu, "|\n";
echo 'tek uzunluk:  ', strlen($tek), "\n";
echo 'cift uzunluk: ', strlen($cift), "\n";
echo 'ters bolu cizgi: ', strlen('a\\b'), ' ', strlen('a\nb'), ' ', strlen("a\nb"), "\n";
```

```
tek:   merhaba $ad\n|
cift:  merhaba Ada
|
suslu: merhaba Adax|
tek uzunluk:  13
cift uzunluk: 12
ters bolu cizgi: 3 4 3
```

**KN12.** Tek tırnaklı dizgi `$ad` ve `\n` olduğu gibi çıktı, uzunluğu bu yüzden on üç oldu. Çift tırnaklı dizgide `$ad` yerine `Ada` geldi ve `\n` tek bir satır sonu karakteri oldu. Süslü parantez, değişken adının nerede bittiğini belirler. Son satır farkı karakter düzeyinde gösterir: tek tırnakta `\n` iki karakterdir, çift tırnakta bir. İkisi de bildirim üretmez; tek tırnakla yazılmış bir `\n` beklenen satır sonunu sessizce vermez.

## Yorum Biçimleri

PHP üç yorum biçimi tanır: `#` ve `//` satır sonuna kadar, `/* */` ise kapanışına kadar sürer. Çok satırlı yorumlar iç içe geçmez: ilk `*/` yorumu bitirir. Aşağıdaki dosya beş `echo`'yu farklı yorumlarla çevreler.

```php
<?php
// yorum_turu.php — yorum biciminin nerede bittigini olcer
echo "1\n"; # satir sonu yorumu
echo "2\n"; // satir sonu yorumu
echo "3\n"; /* satir ici yorum */ echo "4\n";
/* dis yorum /* ic yorum */ echo "5\n";
```

```
1
2
3
4
5
```

**KN13.** Beş satırın beşi de basıldı. Dördüncü satırdaki `/*` ikinci kez açıldığında yorum derinleşmedi; ilk `*/` yorumu kapattı ve `echo "5\n"` kod olarak çalıştı. Yorum yazarken bir bloğu iç içe kapatmaya güvenen kod, kapanıştan sonrasını çalıştırır. Bu da sessiz sınıftadır: hata ya da uyarı yoktur, çalışan kodun miktarı artmıştır.

## echo ve print

PHP'de ekrana yazan iki dil yapısı vardır ve ikisi aynı değildir. `echo` virgülle ayrılmış birden çok değer alır ve bir değer döndürmez. `print` tek değer alır ve her zaman `1` döndürür; bu yüzden bir ifadenin içinde kullanılabilir. Aşağıdaki dosya iki davranışı ve dizi elemanının çift tırnak içindeki yazımını ölçer.

```php
<?php
// yazdir.php — print deger dondurur, echo cok argumanlidir, dizi elemani cift tirnakta cozulur
$sonuc = print "a\n";
echo 'print dondurdu: ', $sonuc, "\n";
echo 'bir', 'iki', "\n";

$dizi = [10, 20];
echo "dizi: $dizi[0]-$dizi[1]\n";
echo 'tek tirnakta: $dizi[0]', "\n";
```

```
a
print dondurdu: 1
biriki
dizi: 10-20
tek tirnakta: $dizi[0]
```

**KN14.** `print` satırı yazdı ve `1` döndürdü; `echo` ise iki dizgiyi araya hiçbir şey koymadan art arda yazdı. Çift tırnaklı dizgide `$dizi[0]` elemanın değeriyle yer değiştirdi, tek tırnaklıda olduğu gibi kaldı. Hiçbiri bildirim üretmez; farkı yalnız çıktıya bakarak görmek mümkündür.

## Sınırlayıcı Ölçüm

Sözdizim hatalı dosya hiç çalışmaz kuralı, her dosya için ayrı geçerlidir. **KN15.** Bir dosya başka bir dosyayı `include` ile çekiyorsa, hatalı olan çekilen dosyadır ve ana dosya çoktan çalışmaya başlamıştır. Çekilen dosya yürütme sırasında ayrıştırıldığı için hata, o noktada bir `ParseError` olarak fırlatılır ve `try` ile `catch` yakalayabilir. Aşağıdaki dosya, daha önce yazılan `bozuk.php`'yi çeker.

```php
<?php
// ana.php — sozdizim hatali dosya dahil edilir; ana dosya calismaya baslamistir
echo "ana basladi\n";
try {
    include 'bozuk.php';
} catch (ParseError $hata) {
    echo 'yakalandi ', get_class($hata), "\n";
}
echo "ana bitti\n";
```

```
ana basladi
yakalandi ParseError
ana bitti
```

Ana dosya üç satırını da bastı, `bozuk.php`'nin `once` satırı ise çıkmadı: çekilen dosya kendi içinde yine hiçbir satırını çalıştırmadı. Kural aynı kaldı, kapsamı değişti: ayrıştırma dosya başına yapılır ve bir dosyanın başarısızlığı ancak o dosyayı çekmekte olan dosyanın yakalayıcısına kadar ulaşır. Yakalayıcı yoksa `ParseError` da durdurur sınıfına düşer.

## Özet

- Dosya çalıştırılmadan önce bütünüyle ayrıştırılır; sözdizim hatalı dosyanın tek bir satırı bile çalışmaz.
- Yürütmede fırlayan hata önceki çıktıyı korur: `fatal.php` bir satır bastı, `bozuk.php` hiç basmadı; ikisi de 255 ile çıktı.
- Bu dersin ölçü sınıfı durdurur: sözdizim hatası yürütmeyi başlamadan keser, yürütmede fırlayan hata başladıktan sonra keser.
- Yerleşik sunucuda sözdizim hatalı dosya gövdesiz `500` verir; yürütmede fırlayan hata gövde başladıktan sonra `200` ile kısmi çıktı bırakır.
- `?>` ve `<?=` etiketleri kod ile şablonu karıştırır; yalnız kod taşıyan dosyada kapanış etiketi yazılmaz, çünkü ardından gelen fazla satır sonu çıktıya bayt ekler.
- Kural dosya başınadır: dahil edilen dosyadaki sözdizim hatası, ana dosya çalıştıktan sonra yakalanabilir bir `ParseError` olarak fırlar.

## Sonraki Adım

Dosyanın çalışmaya başladığı ve etiketlerin içinde ne olduğu belli oldu. Değişkenler ve Veri Tipleri dersi, kodun içinde bir değerin tipinin sinyal vermeden değişip değişmediğini ölçüyor: bir değer tipini kaybedebilir mi?
