aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Geliştirme

PHP PSR-4 Otomatik Yükleme: Namespace ve Dizin Eşlemesi

PHP PSR-4, sınıflarınızı tek tek require etmeden, yalnızca isimlerine bakarak doğru dosyadan otomatik yüklemenizi sağlayan bir otomatik yükleme (autoloading) standardıdır. Temel fikri tek cümlede özetlemek mümkün: bir namespace ön ekini bir taban dizine bağlarsınız, geri kalan namespace parçaları da klasör yoluna birebir karşılık gelir. Bu yazıda PSR-4'ün kurallarını, composer.json ile nasıl yapılandırıldığını ve günlük geliştirmede karşılaşılan tipik hataların nasıl çözüldüğünü gerçek örneklerle ele alıyoruz.

Autoloading neden gerekli?

PHP'nin ilk yıllarında her sınıfı kullanmadan önce dosyasını elle dahil etmeniz gerekirdi. Orta ölçekli bir projede dosyanın başı onlarca require_once satırıyla dolardı ve bir dosyayı taşıdığınızda yolları tek tek güncellemek gerekirdi. Autoloading bu sıkıntıyı ortadan kaldırır: PHP, tanımlı olmayan bir sınıfla ilk kez karşılaştığında kayıtlı bir geri çağırma fonksiyonunu (autoloader) tetikler ve ilgili dosyayı o an yükler.

Bu mekanizmanın çekirdeği spl_autoload_register() fonksiyonudur. PSR-4, bu fonksiyona kaydedilecek autoloader'ın nasıl davranması gerektiğini tanımlayan ortak bir sözleşmedir. Standardı PHP-FIG (Framework Interop Group) yayımladı ve bugün Laravel, Symfony, Guzzle dahil neredeyse tüm modern ekosistem bu kurala göre çalışır. Sayesinde farklı kütüphaneler aynı autoloader'ı paylaşabilir ve sınıf isimlerinden dosya yolunu tahmin etmek tamamen öngörülebilir hâle gelir.

PSR-4'ün temel kuralı

PSR-4'e göre tam nitelikli (fully qualified) bir sınıf adı üç parçadan oluşur: bir namespace ön eki, ara namespace'ler ve sınıf adı. Bir örnekle bakalım. Diyelim ki şu eşlemeyi tanımladınız: App\ ön eki src/ dizinine bağlı. O zaman:

  • App\Mailer sınıfı → src/Mailer.php
  • App\Services\Invoice sınıfı → src/Services/Invoice.php
  • App\Http\Controllers\HomeControllersrc/Http/Controllers/HomeController.php

Kural mekaniği şudur: namespace ön eki (burada App\) taban dizinle (src/) yer değiştirir; kalan her namespace ayıracı (\) bir dizin ayıracına (/) dönüşür; en sona .php eklenir. Dikkat edilmesi gereken üç nokta var:

  • Eşleme büyük/küçük harfe duyarlıdır. App\Mailer dosyası Mailer.php olmalıdır, mailer.php değil. Bu kural Linux sunucularda kritiktir; macOS/Windows yerelde affeder, canlıda kırılır.
  • Dosya adı, içindeki sınıf adıyla aynen aynı olmalıdır.
  • Ön ek mutlaka bir taban diziye karşılık gelmeli; ön ekin kendisi bir klasör adı içermez, doğrudan o klasöre eşlenir.

composer.json ile PSR-4 yapılandırması

Pratikte kendi autoloader'ınızı elle yazmazsınız; Composer'ın ürettiği autoloader'ı kullanırsınız. composer.json dosyasının autoload bölümüne PSR-4 eşlemenizi eklemeniz yeterlidir:

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    }
}

JSON içinde ters bölü işaretinin kaçışlı yazıldığına (App\\) dikkat edin. Birden fazla ön ek de tanımlayabilirsiniz; örneğin uygulama kodu ile test kodunu ayırmak yaygındır:

{
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    }
}

Burada autoload-dev yalnızca geliştirme ortamında devreye girer; üretimde composer install --no-dev ile kurulduğunda test namespace'i yüklenmez. Eşlemeyi ekledikten veya değiştirdikten sonra autoload haritasını yeniden üretmeniz gerekir:

composer dump-autoload

Bu komut vendor/composer/ altındaki haritaları günceller. Yalnızca yeni bir PSR-4 ön eki eklediğinizde veya namespace yapısını değiştirdiğinizde çalıştırmanız gerekir; var olan bir namespace'e yeni sınıf eklemek dump gerektirmez, çünkü PSR-4 dosyayı yoldan tahmin eder.

Kullanım: tek satırlık giriş noktası

Eşleme hazır olduktan sonra projenizin giriş noktasında (örneğin public/index.php) yalnızca Composer'ın ürettiği autoloader'ı dahil etmeniz yeterlidir:

require __DIR__ . '/../vendor/autoload.php';

use App\Services\Invoice;
use App\Mailer;

$invoice = new Invoice();
$mailer  = new Mailer();

Artık hem kendi sınıflarınız hem de kurduğunuz tüm paketler isimleri çağrıldığı anda yüklenir. Sınıf dosyasının kendisi de namespace bildirimiyle başlamalıdır; örneğin src/Services/Invoice.php şöyle görünür:

<?php

namespace App\Services;

class Invoice
{
    public function total(): float
    {
        return 0.0;
    }
}

Buradaki namespace App\Services; satırı, dosyanın PSR-4 eşlemesindeki yeriyle birebir tutarlı olmalıdır. Tutarsızlık, en sık karşılaşılan "Class not found" hatasının kaynağıdır.

PSR-4, classmap ve files arasındaki fark

Composer üç farklı autoload stratejisi destekler ve hangisini ne zaman kullanacağınızı bilmek işinizi kolaylaştırır:

  • psr-4: Namespace'i dizine eşler ve dosyayı yoldan türetir. Modern kodun varsayılan tercihidir; yeni sınıf eklemek dump gerektirmez.
  • classmap: Belirtilen klasörleri tarar ve her sınıf için doğrudan dosya yolunu bir haritaya yazar. Namespace kuralına uymayan eski (legacy) kod için kullanışlıdır, ama yeni sınıf eklendiğinde dump-autoload gerektirir.
  • files: Sınıf değil, fonksiyon tanımları içeren dosyaları her istekte koşulsuz yükler. Genellikle global yardımcı (helper) fonksiyonlar için kullanılır.

Çoğu projede yalnızca psr-4 yeterlidir. classmap ve files, çoğunlukla namespace'siz eski kütüphaneleri entegre ederken devreye girer. Modern bir projede en sağlıklı yaklaşım, tüm uygulama kodunuzu tutarlı bir PSR-4 ağacı altında toplamak; geri kalan iki stratejiyi yalnızca gerçekten gerektiğinde, istisnai durumlar için kullanmaktır. Böylece klasör yapısı sınıf adlarından doğrudan okunabilir ve yeni gelen bir geliştirici bir sınıfın hangi dosyada olduğunu tahmin etmek için hiçbir araca ihtiyaç duymaz.

Üretimde autoload optimizasyonu

PSR-4 esnektir ama bu esnekliğin küçük bir maliyeti vardır: çalışma anında PHP, sınıf adından dosya yolunu hesaplar ve diskte dosyanın varlığını kontrol eder. Üretim ortamında bunu önceden hesaplayarak hızlandırabilirsiniz:

composer dump-autoload --optimize

Bu komut (kısaca -o) tüm PSR-4 sınıflarını tarar ve bir classmap'e dönüştürür; böylece çalışma anındaki dosya aramaları ortadan kalkar. Genellikle dağıtım (deploy) adımında şu kombinasyonu kullanırsınız:

composer install --no-dev --optimize-autoloader

Tek dikkat: optimize edilmiş classmap statiktir. Üretimde yeni bir sınıf dosyası eklerseniz, dump'ı tekrar çalıştırana kadar yeni sınıf bulunamaz. Bu yüzden optimize bayrağı geliştirme ortamı için değil, yalnızca dağıtım için uygundur.

Sık Sorulan Sorular

"Class not found" hatası alıyorum, nereye bakmalıyım?

Önce üç şeyi kontrol edin: dosyadaki namespace bildirimi PSR-4 eşlemesiyle tutarlı mı, dosya adı sınıf adıyla büyük/küçük harf dahil aynen aynı mı, ve composer.json'daki taban dizin doğru mu. Yeni bir ön ek eklediyseniz composer dump-autoload çalıştırmayı unutmayın. Hata yalnızca canlıda çıkıyorsa, neredeyse her zaman büyük/küçük harf uyuşmazlığıdır; Linux dosya sistemi harfe duyarlıdır.

PSR-4 ile PSR-0 arasındaki fark nedir?

PSR-0 daha eski standarttır ve namespace içindeki alt çizgileri (_) dizin ayıracı olarak yorumlayıp ön ekin tamamını dizin yapısına yansıtmasıyla daha katıdır. PSR-4 ise ön eki doğrudan bir taban dizine eşler, böylece daha sığ ve temiz klasör yapıları kurabilirsiniz. PSR-0 bugün kullanımdan kaldırılmıştır; yeni projelerde her zaman PSR-4 tercih edin.

Her yeni sınıf için dump-autoload çalıştırmalı mıyım?

Hayır. PSR-4 dosyayı namespace'den türettiği için, var olan bir eşlemeye yeni bir sınıf eklediğinizde ek bir komut gerekmez; sınıf doğrudan çalışır. dump-autoload yalnızca yeni bir PSR-4 ön eki eklediğinizde, classmap kullandığınızda veya üretim için optimize ettiğinizde gereklidir.

PHP projenizde autoload yapısı mı karıştı? Namespace organizasyonu, "class not found" hataları, eski kodu PSR-4'e taşıma ya da Laravel/Symfony tabanlı bir projenin temiz mimarisi için yardıma ihtiyacınız olursa benimle iletişime geçin — kod tabanınızı birlikte sağlam bir temele oturtalım.

Bu kategorideki tüm yazılar →

Devamı için