PHP'nin temel sözdizimi dört kuraldan oluşur: kod <?php ile açılıp ?> ile kapanan etiketlerin arasına yazılır, her deyim noktalı virgülle biter, yorumlar //, # veya /* */ ile yazılır ve ekrana çıktı çoğunlukla echo ile verilir. Etiketlerin dışında kalan her şey (örneğin HTML) PHP tarafından işlenmeden olduğu gibi çıktıya gönderilir.
Bu kurallar basit görünse de yeni başlayanların ilk hataları genellikle buradan çıkar: dosya sonunda unutulan bir boşluk, iç içe yazılmış blok yorumlar veya echo satırında operatör önceliğinin beklenmedik sonucu gibi. Bu yazıda her kuralı çalıştırılmış örneklerle ve PHP 8.5.12'nin verdiği gerçek hata mesajlarıyla ele alıyoruz. Serinin tamamı için PHP öğrenme rehberi sayfasına bakabilirsiniz.
PHP etiketleri: <?php, <?= ve kapanış etiketi

PHP bir dosyayı işlerken yalnızca açılış ve kapanış etiketleri arasındaki bölümü kod olarak yorumlar. Standart açılış etiketi <?php biçimindedir ve kılavuza göre etiketten hemen sonra bir boşluk karakteri (boşluk, sekme veya satır sonu) gelmek zorundadır. Bu boşluk unutulup kod etikete bitiştirilirse dosya sözdizimi hatası verir.
İkinci etiket kısa yazdırma etiketi <?= biçimindedir ve <?php echo ifadesinin kısaltmasıdır. Şablonlarda tek bir değeri yazdırmak için çok kullanılır; echo sayfası bu etiketin short_open_tag ayarı kapalı olsa bile çalıştığını belirtir. Bir de yalnızca <? biçimindeki kısa etiket vardır; varsayılan olarak açıktır ama php.ini'deki short_open_tag yönergesiyle veya derleme seçeneğiyle kapatılabildiği için kılavuz, uyumluluk adına yalnızca <?php ?> ve <?= ?> kullanmanızı önerir.
<?php
echo "Merhaba\n"; // çıktı: Merhaba
echo 'Bu ', 'bir ', 'deneme', "\n"; // çıktı: Bu bir deneme
print "print de yazdırır\n"; // çıktı: print de yazdırır
echo 6 * 7, "\n"; // çıktı: 42
Dosya sonunda kapanış etiketi yazmayın
Dosya yalnızca PHP kodu içeriyorsa sondaki ?> etiketini yazmamak tercih edilen yöntemdir. Kılavuzun gerekçesi şöyle: kapanış etiketinden sonra yanlışlıkla kalan bir boşluk veya fazladan satır sonu çıktı olarak gönderilir. Böyle bir dosya include veya require ile başka bir dosyaya eklendiğinde, siz henüz bir şey yazdırmak istemezken çıktı başlamış olur ve sonradan yanıt başlığı (header) eklemeniz engellenebilir. Kapanış etiketini hiç yazmazsanız bu riski tamamen ortadan kaldırırsınız.
Kapanış etiketi bir başka ayrıntıyı da beraberinde getirir: ?> işaretinden hemen sonra gelen tek satır sonu, etiketin parçası sayılır ve çıktıya yazılmaz. Aşağıdaki örnekte "Bir" ile "İki" bu yüzden aynı satırda birleşir; aynı kural <?= ?> etiketi için de geçerlidir.
<?php echo "Bir"; ?>
İki
<?= "Üç" ?>
Dört
Birİki
ÜçDörtPHP'yi HTML içine gömmek
Etiketlerin dışındaki içerik işlenmeden çıktıya gittiği için PHP dosyası aynı anda hem HTML hem kod içerebilir. Bu, PHP'nin şablon dili olarak doğmasının da nedenidir. Etiket kapandığında yorumlayıcı bir sonraki açılış etiketine kadar gördüğünü olduğu gibi yazar. Koşul veya döngü bloğunun ortasındaysa, o HTML parçasını yazıp yazmayacağına bloğun koşuluna bakarak karar verir.
Şablonlarda süslü parantez yerine iki nokta ve endforeach;, endif; gibi kapanış kelimeleri kullanan alternatif sözdizimi okunaklılığı artırır. Kılavuz, büyük metin bloklarını echo ile basmak yerine PHP modundan çıkıp HTML olarak yazmanın genellikle daha verimli olduğunu da not eder.
<?php $meyveler = ['elma', 'armut', 'ayva']; ?>
<ul>
<?php foreach ($meyveler as $meyve): ?>
<li><?= $meyve ?></li>
<?php endforeach; ?>
</ul>
<ul>
<li>elma</li>
<li>armut</li>
<li>ayva</li>
</ul>Çıktıda boş satır olmamasının nedeni yine kapanış etiketinden sonraki satır sonunun yutulmasıdır. Alternatif sözdiziminin if, elseif ve switch ile kullanımı koşul yapıları yazısında, döngülerle kullanımı döngüler yazısında ayrıntılı anlatılıyor.
Noktalı virgül: deyimleri ayırma kuralı

C ve Perl'de olduğu gibi PHP'de de her deyim noktalı virgülle bitmelidir. Tek istisna, bir PHP bloğunun son satırıdır: kapanış etiketi örtük olarak noktalı virgül yerine geçer, bu yüzden <?php echo "x" ?> geçerli bir yazımdır. Kapanış etiketi olmayan dosyalarda bu istisnadan yararlanamazsınız; her satırın sonunda noktalı virgül bulunmalıdır.
Noktalı virgülü unuttuğunuzda PHP hatayı genellikle bir sonraki satırda bildirir, çünkü ifadenin bittiğini ancak yeni bir anahtar kelimeyle karşılaştığında anlar. Aşağıdaki dosyada eksik noktalı virgül ikinci satırdadır ama mesaj üçüncü satırı gösterir:
<?php
echo 'Birinci satır'
echo 'İkinci satır';
Parse error: syntax error, unexpected token "echo", expecting "," or ";" in /yol/ornek.php on line 3Mesajdaki "expecting "," or ";"" kısmı ipucunu verir: PHP, echo deyiminin devamında ya başka bir argüman için virgül ya da bitiş için noktalı virgül bekliyordu. Bir hata mesajı belirtilen satırda anlamsız görünüyorsa bir önceki satırın sonuna bakın. Bu tür ayrıştırma hatalarının diğer biçimleri Fatal error ve ParseError yazısında toplanmıştır.
PHP'de yorum satırları
PHP üç yorum biçimini destekler: C++ tarzı tek satırlık //, kabuk tarzı tek satırlık # ve C tarzı çok satırlı /* ... */. Tek satırlık yorumlar satırın sonuna veya PHP bloğunun sonuna kadar geçerlidir; hangisi önce gelirse. Bu ikinci kural şaşırtıcı bir sonuç doğurur: // ile başlayan bir yorumun içine ?> yazarsanız yorum orada biter ve sonrası HTML olarak çıktıya gider.
<?php
echo 'A'; // bu bir yorum ?> B
<?php
# kabuk tarzı tek satırlık yorum
/* çok satırlı
yorum */
echo "\nC\n";
A B
CÇok satırlı yorumlarda ise asıl tuzak iç içe yazmaktır. Blok yorum ilk karşılaşılan */ işaretinde biter. İçinde zaten blok yorum bulunan bir kod parçasını geçici olarak devre dışı bırakmak için tamamını /* */ içine alırsanız, içteki kapanış dıştaki yorumu erken bitirir ve kalan */ sözdizimi hatası verir:
<?php
echo "a";
/* dış yorum /* iç yorum */ */
echo "b";
Parse error: syntax error, unexpected token "*", expecting end of file in /yol/ornek.php on line 3echo ve print farkı

echo ve print fonksiyon değil dil yapısıdır (language construct); bu yüzden argümanlarını parantez içine almak gerekmez. İkisi de verilen değeri metne çevirip yazdırır ve kendiliğinden satır sonu veya boşluk eklemez. Metin olmayan değerler, strict_types açık olsa bile metne dönüştürülür. Aralarındaki farklar şöyle özetlenebilir:
| Özellik | echo | |
|---|---|---|
| Argüman sayısı | Virgülle ayrılmış birden fazla | Yalnızca bir |
| Dönüş değeri | Yok | Her zaman 1 |
| İfade içinde kullanım | Kullanılamaz | Kullanılabilir (ör. üçlü operatör içinde) |
| Kısa yazım | <?= ifade ?> | Yok |
| Değişken fonksiyon veya isimli argüman | Desteklenmez | Desteklenmez |
print her zaman 1 döndürdüğü için bir ifadenin parçası olabilir; echo ise değer döndürmediğinden örneğin üçlü operatörün dallarında kullanılamaz. Pratikte çoğu kod echo tercih eder, çünkü birden fazla parçayı virgülle verebilmek hem okunaklıdır hem de öncelik sorunlarını önler.
<?php
$sonuc = print "Merhaba\n"; // çıktı: Merhaba
var_dump($sonuc); // çıktı: int(1)
echo 'Toplam: ' . 1 + 2, "\n"; // çıktı: Toplam: 3
echo 'Toplam: ', 1 + 2, "\n"; // çıktı: Toplam: 3
echo(1 + 2) * 3, "\n"; // çıktı: 9
Parantezler yanıltıcı olabilir
echo("merhaba") yazımı hata vermez ve fonksiyon çağrısına benzer, ama buradaki parantez echo sözdiziminin değil yazdırılan ifadenin parçasıdır. Yukarıdaki örnekteki echo(1 + 2) * 3 satırı bu yüzden 9 yazar: önce parantez içi hesaplanır, sonra sonuç 3 ile çarpılır ve tüm ifade tek argüman olarak yazdırılır. echo("a", "b") ise ayrıştırma hatası verir, çünkü parantez içindeki virgüllü liste geçerli bir ifade değildir.
print bir ifadenin parçası olduğunda
print ifade olarak kullanılabildiği için, mantıksal operatörlerle birleştiğinde neyin önce değerlendirileceği şaşırtıcı olabilir. print kendisinden sonra gelen ifadenin tamamını argüman olarak alır. Aşağıdaki ilk satırda soldaki print aslında "merhaba " && print "dünya" ifadesinin sonucunu yazdırır: önce sağdaki print çalışıp "dünya" yazar ve 1 döndürür, ardından "merhaba " && 1 ifadesi true olur ve metne çevrildiğinde "1" yazdırılır. İstenen sıra ancak her print parantez içine alınarak elde edilir.
<?php
print "merhaba " && print "dünya";
echo "\n";
(print "merhaba ") && (print "dünya");
echo "\n";
dünya1
merhaba dünyaBirleştirme ve öncelik tuzağı
Nokta (.) birleştirme operatörü üçlü operatörden daha yüksek önceliğe sahiptir. Bu yüzden aşağıdaki satır niyet edildiği gibi "Merhaba misafir" yazmaz: önce 'Merhaba ' . isset($ad) birleştirilir, oluşan boş olmayan metin doğru sayılır ve üçlü operatör tanımsız $ad değişkenini döndürür.
<?php
echo 'Merhaba ' . isset($ad) ? $ad : 'misafir';
Warning: Undefined variable $ad in /yol/ornek.php on line 2Çözüm ya ifadeyi parantez içine almak ya da parçaları virgülle ayrı argümanlar olarak vermektir: echo 'Merhaba ', isset($ad) ? $ad : 'misafir';. PHP 8.0'dan önce nokta operatörü toplama ve çıkarmayla aynı önceliğe sahipti; echo 'Toplam: ' . 1 + 2 satırı eski sürümlerde farklı sonuç veriyordu. PHP 8'de toplama önce yapılır ve yukarıdaki örnekte gördüğünüz gibi "Toplam: 3" yazılır. Öncelik kurallarının tamamı operatörler yazısında tablo hâlinde verilmiştir.
Hepsi bir arada: küçük bir ürün kartı şablonu
Şimdiye kadar anlatılan kuralları tek bir dosyada birleştirelim. Aşağıdaki şablon önce bir blok yorumla dosyanın amacını açıklıyor, PHP bölümünde veriyi hazırlıyor, ardından kapanış etiketiyle HTML moduna geçip değerleri kısa yazdırma etiketiyle yerleştiriyor. Stok durumuna göre farklı HTML parçası göstermek için alternatif if sözdizimi kullanılıyor. Bu dosya HTML ile bittiği için burada kapanış etiketleri zorunludur; "dosya sonunda kapanış etiketi yazmayın" kuralı yalnızca saf PHP dosyaları içindir.
<?php
/*
* urun.php: tek bir ürün kartını HTML olarak yazdırır.
*/
$urun = [
'ad' => 'Çay Bardağı <6\'lı>',
'fiyat' => 149.9,
'stok' => 0,
];
$fiyatMetni = number_format($urun['fiyat'], 2, ',', '.') . ' TL'; // Türkçe biçim
?>
<div class="urun">
<h2><?= htmlspecialchars($urun['ad']) ?></h2>
<p>Fiyat: <?= $fiyatMetni ?></p>
<?php if ($urun['stok'] > 0): ?>
<button>Sepete ekle</button>
<?php else: ?>
<p>Stokta yok</p>
<?php endif ?>
</div>
<div class="urun">
<h2>Çay Bardağı <6'lı></h2>
<p>Fiyat: 149,90 TL</p>
<p>Stokta yok</p>
</div>Çıktıda dikkat edilecek üç nokta var. Birincisi, ürün adındaki <, > ve tek tırnak karakterleri htmlspecialchars() sayesinde HTML varlıklarına dönüştü; böylece tarayıcı onları etiket olarak yorumlamaz. Bu karakterlerin nasıl kodlandığını HTML entity yazısında bulabilirsiniz. İkincisi, stok sıfır olduğu için yalnızca "Stokta yok" paragrafı yazıldı; koşulu sağlamayan HTML bloğu PHP etiketlerinin dışında olmasına rağmen atlandı. Üçüncüsü, ?> etiketlerinden sonraki satır sonları yutulduğu için çıktıda boş satır oluşmadı. Fiyatı Türkçe biçimde yazan number_format() fonksiyonu ise sprintf ve number_format yazısında ayrıntılı anlatılıyor.
Sık yapılan hatalar
- Etiketten sonra boşluk bırakmamak:
<?phpile kod arasında en az bir boşluk veya satır sonu olmalıdır; bitişik yazım sözdizimi hatasıdır. - Dosya sonunda kapanış etiketi ve boşluk bırakmak: Yalnızca PHP içeren dosyalarda
?>yazmayın; istenmeyen çıktının en yaygın kaynağıdır. - Hata satırına takılıp kalmak: Noktalı virgül eksikliği genellikle bir sonraki satırda raporlanır.
- Blok yorumları iç içe yazmak: İlk
*/yorumu bitirir; büyük bir bölümü kapatmak için her satırın başına//koymak daha güvenlidir. - echo satırında birleştirme ile üçlü operatörü karıştırmak: Parantez kullanın veya parçaları virgülle ayırın.
- Kısa etikete (
<?) güvenmek: Sunucu ayarına bağlıdır; taşınabilir kod için<?phpkullanın.
Sık Sorulan Sorular
PHP dosyasının sonunda ?> yazmak zorunlu mu?
Hayır. Dosya PHP koduyla bitiyorsa kapanış etiketi isteğe bağlıdır ve kılavuz onu yazmamayı önerir. Böylece dosya sonuna kaçan boşlukların çıktıya karışması engellenir.
echo mu print mi kullanmalıyım?
Çoğu durumda echo yeterlidir; birden fazla argüman alır ve kısa yazımı (<?=) vardır. Bir ifadenin içinde yazdırma yapıp dönüş değerine ihtiyaç duyduğunuz nadir durumlarda print kullanılabilir.
Tek satırlık yorum için // ile # arasında fark var mı?
Davranış olarak fark yoktur; ikisi de satırın veya PHP bloğunun sonuna kadar geçerlidir. Tek fark PHP 8 ile gelen kuraldır: #[ bir öznitelik başlatır, yorum başlatmaz.
Bir .html dosyasının içine PHP kodu yazabilir miyim?
PHP etiketleri dosyanın içinde her yerde kullanılabilir, ama kodun çalışması için dosyanın PHP yorumlayıcısından geçmesi gerekir. Komut satırında php komutu dosya uzantısına bakmaz; kılavuz, çalıştırılacak dosyanın .php uzantılı olmasının zorunlu olmadığını belirtir. Web sunucusunda ise hangi uzantıların PHP'ye gönderileceği sunucu yapılandırmasına bağlıdır; bu yüzden şablonlarınızı .php uzantısıyla kaydetmek en sorunsuz yoldur.
Bir dosyayı çalıştırmadan sözdizimini nasıl kontrol ederim?
php -l dosya.php komutu dosyayı yalnızca ayrıştırır. Sorun yoksa "No syntax errors detected" yazar, varsa yukarıdakilere benzer bir Parse error mesajı gösterir. Diğer komut satırı seçenekleri PHP CLI yazısında anlatılıyor.
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 değişkenler ve kapsam · PHP operatörler ve öncelik · PHP if, switch ve match · HTML entity nedir?