Autoload (Özdevinimli) Sınıf Yükleme

Autoload Nedir? Ne İşe Yar?

Sınıflarla ilgili işlem yaptığımız anda o sınıfın kaynak dosyasını sayfamıza otomatik dahil eder. Bu yazımda __autoload ve spl_autoload_register fonksiyonlarından bahsedeceğim.

Basit bir örnekle anlatıma başlayayım.

<?php

function __autoload($sinif_ismi)
{
    $sinif_adresi = __DIR__.DIRECTORY_SEPARATOR."lib".DIRECTORY_SEPARATOR.$sinif_ismi . ".php";

    //is_readable() : Bir dosyanın mevcut ve okunabilir olup olmadığını söyler
    if (is_readable($sinif_adresi)) {
        require $sinif_adresi;
    }
}

echo Kullanici::TANIM;

__autoload ( $class ){/* ... */} fonksiyonu erişmeye çalıştığınız sınıfları bulamazsa otomatik devreye girer ve sınıf adını parametre olarak bu fonksiyona gönderir. İstediğimiz işlemi bu fonksiyonun içinde yapabiliriz.

Yukarıdaki örnekte Kullanici sınıfımda bulunan TANIM sabitini ekrana yazdırdım. Kullanici sınıfım sayfama dahil edilmediği için __autoload($sinif_ismi = "Kullanici")){} fonksiyonu çalıştı.

Fonksiyonum içinde require "C:\xampp\htdocs\oop\lib\Kullanici.php" kod satırıyla Kullanici sınıfımı sayfama otomatik dahil etmiş oldum.

Namespace kullansaydık?

Sınıfımızda namespace tanımladığımız anda işler biraz daha karışıyor.

 

Örneğin:

<?php

use Magaza\Kullanici as Magaza;

function __autoload($sinif_ismi) {
    $sinif_adresi = __DIR__.DIRECTORY_SEPARATOR."lib".DIRECTORY_SEPARATOR.$sinif_ismi . ".php";
    if (is_readable($sinif_adresi)) {
        require $sinif_adresi;
    }
}

echo Magaza::TANIM .'</br>';

Bu sefer autoload fonksiyonuna paramatre olarak "Magaza\Kullanici" gönderildi. 

"BULUNDUĞU DİZİN->lib->Magaza->Kullanici.php" yolunda, dosyamı bulursa require "C:\xampp\htdocs\oop\lib\Magaza\Kullanici.php" ile sayfama dahil edecektir. Fakat burada bir sıkıntı var eğer *nix işletim sistemlerinden biriyle çalışıyorsanız Kullanici.php dosyasına erişemeyeceksiniz. Sebebi ise var/www/lib/Magaza\Kullanici.php 

Windows da klasör separatörü "\" olduğu için namespace'lere direk klasör muamelesi yapacaktır. Fakat *nix sistemlerde bu seperatör "/" dir. Bu yüzden kesinlikle namespace separatörünü(\), klasör separatörüyle değiştirmeniz gerekmektedir. 

$sinif_ismi = str_replace('\\', DIRECTORY_SEPARATOR, $sinif_ismi);

Bu işlemi uygularsak çıktımız: var/www/lib/Magaza/Kullanici.php  olur. Bu dosyaya ulaşırsa, Kullanici sınıfını çalışmamıza dahil edecektir. Namespace'leri autoload'lar için nasıl tanımlamamız gerekir? yada hangi dönüşümüleri yapmamız gerekir? Bunları incelemek isterseniz PHP Kod Standartları yazımı okumanızı tavsiye ederim.


Birden fazla klasöre hitap etme?

Yukarıdaki örnekler de hep sınıfların lib klasörünün altında olması senaryosu vardı. Peki tüm sınıflarım aynı klasörün altında olma zorunluluğu mu var? Tabi ki yok. Örneğin app/models, app/controllers klasörlerinde de sınıflarım var. Bunları nasıl dahil ederiz? Cevap: Deneme yanılma yoluyla 

function __autoload($sinif_ismi) {

    $sinif_ismi  = str_replace("\\", DIRECTORY_SEPARATOR, $sinif_ismi);

    $lib = __DIR__.DIRECTORY_SEPARATOR."lib".DIRECTORY_SEPARATOR.$sinif_ismi . ".php";
    $controllers = __DIR__.DIRECTORY_SEPARATOR."app".DIRECTORY_SEPARATOR."Controllers".DIRECTORY_SEPARATOR.$sinif_ismi . ".php";
    $models = __DIR__.DIRECTORY_SEPARATOR."app".DIRECTORY_SEPARATOR."Models".DIRECTORY_SEPARATOR.$sinif_ismi . ".php";

    if (is_readable($lib)) {
        require $lib;
    }else if (is_readable($controllers)) {
        require $controllers;
    }else if (is_readable($models)) {
        require $models;
    }
}

Önce lib klasörüne bakar bulamazsa app/Contollers klasörüne onu da bulamazsa en son app/Models klasörüne bakar. Gayet basit bir kullanımı var fakat bu kodlar arttıkça okunabilirlik neredeyse sıfıra inecektir. Sebebi ise tek bir tane autoload kullanmamız. Keşke birden fazla autoload kullanabilseydik diyecem diyemiyorum. Çünkü PHP spl_autoload fonksiyonu ile bize bu kolaylığıda sağlıyor. :)


spl_autoload Nedir? Ne işe yarar?

__autoload ne işe yarıyorsa bu fonksiyonda aynı işe yarar. Tek farkı kullanımın daha esnek olması. Örnekle inceyelim:

<?php

function autoloadLib($sinif_ismi)
{
    $sinif_ismi  = str_replace("\\", DIRECTORY_SEPARATOR, $sinif_ismi);
    $sinif_adresi = __DIR__.DIRECTORY_SEPARATOR."lib".DIRECTORY_SEPARATOR.$sinif_ismi . ".php";
    if (is_readable($sinif_adresi)) {
        require $sinif_adresi;
    }
}


function autoloadModel($sinif_ismi)
{
    $sinif_ismi  = str_replace("\\", DIRECTORY_SEPARATOR, $sinif_ismi);
    $sinif_adresi = __DIR__.DIRECTORY_SEPARATOR."app".DIRECTORY_SEPARATOR."Models".DIRECTORY_SEPARATOR.$sinif_ismi . ".php";
    if (is_readable($sinif_adresi)) {
        require $sinif_adresi;
    }
}

function autoloadController($sinif_ismi)
{
    $sinif_ismi  = str_replace("\\", DIRECTORY_SEPARATOR, $sinif_ismi);
    $sinif_adresi = __DIR__.DIRECTORY_SEPARATOR."app".DIRECTORY_SEPARATOR."Controllers".DIRECTORY_SEPARATOR.$sinif_ismi . ".php";
    if (is_readable($sinif_adresi)) {
        require $sinif_adresi;
    }
}


spl_autoload_register("autoloadLib");
spl_autoload_register("autoloadModel");
spl_autoload_register("autoloadController");

 

Gördüğünüz gibi autoload'ları, fonksiyonlarla kontrolünü yaptıktan sonra  spl_autoload_register() fonksiyonuyla, autoload'a kaydettim. Her bir grubun işlemini kendi içinde ayarlayarak okunabilirliği __autoload'a göre üst seviyeye çektim.

Siz kullanırken kesinlikle spl_autoload_register() fonksiyonu kullanın çünkü __autoload esnek olmadığı için artık kullanılmıyor. PHP tarafından da ilerleyen sürümlerde biz bu __autoload'ı kaldırabiliriz uyarısı yapılmıştır bilginize.

Tavsiye edilmeyen şeyi niye anlattım derseniz?
Malesef ki bizim Tük bloggerlar bilgisizce bu konuyu anlatmış. Eğer internette autoload diye aratırsanız eski yöntemi göreceksiniz yada birisi spl_autoload_register ile __autoload'ı kıyaslamış ama nasıl kafayla anlatmış onu ben çözemedim. Ben her ikisini de anlatıp __autoload'ın belli bir yerde tıkanacağını onun yerine yeni alternatifini kullanmanız gerektiğini söyleme gereği duydum.

Yorumlarınızı eksik etmeyin. Kendinize iyi bakın. :)


Kategoriler: PHP