Gastroenteroloji ve göğüs cerrahisinde hekimlerin karşılaştığı en ilginç anatomik patolojilerden biri "Özofagus Darlığı"dır (Yemek borusu darlığı). Hasta masaya oturur, iştahı yerindedir; ağzını kocaman açar, koca bir elmayı veya ekmek parçasını çiğneyip yutmak ister. Ağız boşluğu ve çene kasları o lokmayı alacak kadar geniştir. Fakat lokma yutulduğu anda, yemek borusunun orta kısmındaki o daralmış halkaya takılır. Lokma mideye inemez, sıkışır ve vücut bir savunma refleksiyle o lokmayı hiçbir gürültü çıkarmadan, sessizce geri çıkarır (regürjitasyon). Dışarıdan bakan biri hastanın yemeği yediğini sanır; oysa besin mideye hiç ulaşmamıştır. Hiyerarşik boru hattında darlık varsa, kapının geniş olması hiçbir işe yaramaz.
Web yazılımı mimarisinde ve PHP ekosisteminde de web geliştiricilerin ve sistem yöneticilerinin yıllardır düştüğü en yaygın, en komik ama bir o kadar da delirtici tuzak tam olarak bu yemek borusu darlığıdır: upload_max_filesize değerini artırıp, arkasındaki post_max_size ve memory_limit hiyerarşisini unutmak.
Çarşamba 15:30: "Kataloğu Yüklüyorum, Sayfa Başa Dönüyor!"
Bir kurumsal firmanın web yöneticisi veya grafiker arkadaşımız yönetim paneline girer. Şirketin yeni hazırlanan 45 Megabayt boyutundaki yüksek çözünürlüklü PDF ürün kataloğunu siteye yüklemek istemektedir.
WordPress ortam kütüphanesine veya özel PHP paneline girer. Dosya yükleme ekranının altında o tanıdık uyarıyı görür:
"Maksimum dosya yükleme boyutu: 2 MB."
Kullanıcı bilinçlidir. cPanel'e girer, "MultiPHP INI Editor" sekmesini açar. Listeden ilgili parametreyi bulur:
upload_max_filesize = 64MDeğeri 2M'den gururla 64M seviyesine çıkarır ve "Kaydet"e basar. Panelde artık "Maksimum yükleme boyutu: 64 MB" yazmaktadır.
Kullanıcı mutlu bir şekilde dosya yükleme butonuna tıklar, o 45 MB'lık PDF kataloğunu seçer ve "Yükle" der.
Tarayıcının altındaki ilerleme çubuğu %10... %50... %99... %100 olur.
Ve sayfa aniden yenilenir.
Ekranda ne bir yüklenmiş dosya vardır, ne bir onay mesajı, ne de tek bir kırmızı hata uyarısı! Sayfa sanki o butona hiç basılmamış gibi tertemiz, bomboş bir şekilde başa dönmüştür!
Kullanıcı tekrar dener; dosya seçilir, %100 yüklenir, sayfa yenilenir ve BOMBOŞ başa döner!
Kullanıcı üçüncü denemeden sonra çıldırır. Destek masasını arar:
"Sizin sunucunuz kafayı yemiş! 64 MB limit verdim, 45 MB dosya atıyorum; sunucu dosyayı alıyor, tam bitti derken hiçbir hata vermeden sayfayı sıfırlıyor! Dosyam buharlaşıyor resmen! Sunucunuz dosyalarımı yutuyor, sabahtan beri dalga mı geçiyorsunuz benimle?"
PHP'nin Sessiz İntikamı: Boşalan $_POST ve $_FILES
Kullanıcının anlayamadığı o gizemli mekanizma, PHP'nin HTTP isteklerini karşılarken uyguladığı katı ve acımasız hiyerarşide gizlidir.
Bir dosya tarayıcıdan sunucuya gönderilirken tek başına havada uçmaz. Bir HTTP POST paketinin içine sarılarak (multipart/form-data) sunucuya fırlatılır.
İşte o anda PHP'nin kutsal üçlü hiyerarşisi devreye girer:
memory_limit > post_max_size > upload_max_filesizeKullanıcı ne yapmıştır?
upload_max_filesize = 64M(Ağzını 64M açmıştır!)- Fakat
post_max_sizedeğerini varsayılan8Mseviyesinde unutmuştur! (Yemek borusu 8M'de kalmıştır!) memory_limitdeğeri ise belki de32Mseviyesindedir!
Ve PHP çekirdeğinde şu dehşet senaryosu gerçekleşir:
- Tarayıcı 45 MB'lık dosyayı POST paketiyle sunucuya fırlatır.
- Web sunucusu paketi alır, PHP motoruna teslim eder.
- PHP motoru kapıya bakar: Gelen POST paketinin toplam boyutu 46 Megabayt'tır!
- PHP ayar dosyasına bakar:
post_max_size = 8M! - PHP şu kararı verir: "Bu POST paketi benim izin verdiğim 8M sınırını aşmıştır. Bu paketi işlemeyi reddediyorum!"
Ve en ölümcül kısım şudur: PHP bu durumda betiği durdurup ekrana bir Fatal Error basmaz!
Bunun yerine küresel $_POST ve $_FILES dizilerinin içini tamamen boşaltır (empty array)!
Script çalışmaya devam eder. Sizin PHP kodunuz bakar: $_FILES['dosya'] var mı? Yok! Bomboş bir dizi gelmiş! Kod hiçbir veri gelmediğini zanneder, hiçbir hata fırlatmaz ve kullanıcıyı saf saf ana forma geri yönlendirir!
Kullanıcı ekran karşısında dosyasının "buharlaştığını" zannederken, aslında PHP'nin yemek borusu o lokmayı daha kapıda kusmuştur.
Kutsal Üçlü Hiyerarşisi: Matruşka Bebekleri Kuralı
Bu parametreler birbirinin içine geçen Rus matruşka bebekleri gibidir. Dıştaki bebek, içteki bebekten daima daha büyük olmak zorundadır!
[ memory_limit: 256M ] <-- En dıştaki mide (PHP'nin toplam hafızası)
[ post_max_size: 128M ] <-- Ortadaki yemek borusu (Tüm form paketi)
[ upload_max_filesize: 64M ] <-- En içteki lokma (Tek bir dosya boyutu)Bir dosyayı sorunsuz yükleyebilmek için yazılması gereken doğru cerrahi reçete şudur:
; 1. Tek bir dosyanın maksimum boyutu:
upload_max_filesize = 64M
; 2. Formdaki tüm dosyaların ve yazıların toplam boyutu (daima upload'dan büyük olmalı!):
post_max_size = 128M
; 3. Bu işlemi hafızada işleyecek PHP scriptinin bellek tavanı (daima post'tan büyük olmalı!):
memory_limit = 256M
; 4. Büyük dosyanın sunucuya yüklenirken zaman aşımına uğramaması için:
max_execution_time = 300
max_input_time = 300Bu dört satırı php.ini dosyasına yazıp web sunucusunu yeniden başlattığınız anda, o yemek borusu darlığı saniyeler içinde ortadan kalkar.
Kullanıcı 45 MB'lık kataloğu seçip "Yükle"ye basar. Yükleme çubuğu %100 olur, sayfa yeşil bir tik işaretiyle açılır: "Katalog başarıyla yüklendi!"
Parametreler Arasındaki Görünmez Bağları Anlamak
Sistem yönetimi tek bir butonu çevirip mucize beklemek değildir. Bir parametreyi değiştirdiğinizde, onun bağlı olduğu alt ve üst sınırları da hesaba katmak zorundasınız:
upload_max_filesizelokmanın büyüklüğüdür,post_max_sizelokmanın geçtiği boğazdır,memory_limitlokmanın sindirildiği midedir,max_execution_timeise lokmanın sindirilmesi için tanınan süredir.
Bu zincirin tek bir halkasını dar bırakırsanız, sistem bağırmadan, hata vermeden sessizce çöker. Mühendislik, parametrelerin ezbere yazılması değil; o parametrelerin birbirleriyle kurduğu biyolojik dengenin saygıyla yönetilmesidir.