özdevinimli_yükle ve birden dizinleri

6 Cevap php

Ben sadece PHP'nin autoload () fonksiyonu bakarak oldum. Güzel bir fikir gibi görünüyor, ama ben birden çok dizinleri nasıl işleyeceğini emin değilim. Benim şu anki geliştirme temelde operasyon ile alt içine sınıfları gruplama bir kütüphane dizin yapısı vardır. Ben her dizin için () şunlardır ... Gerçekten ben yapmak zorunda değilsiniz umarım beyan etmek zorunda merak ediyorum.

Eğer tavsiyelerde bulunabilir - teşekkürler

6 Cevap

Sen autoloading için gerçekten harika sınıf adları için PEAR Convention bakmak isteyebilirsiniz.

Temel olarak, bu devletler:

The PEAR class hierarchy is also reflected in the class name, each level of the hierarchy separated with a single underscore.

Hangi classe adı HTML_Upload_Error '/' ile '_' yerine sadece bir meselesidir için eklemek dosya bulma anlamına gelir; vererek HTML/Upload/Error.php

Daha fazla açıklama ve örnek bir çift için, makalelere bir göz atabilirsiniz:

BTW : this convention is used by many big Frameworks / libraries ;-)
For instance, Zend Framework uses this convention -- and it's really helpful !

Burada benzer bir amaç için bir süre önce yazdığım bir sınıftır. Ben hala öğrenme aşamasında olduğunu, bu yüzden dahil aptal fikirleri olabilir O zaman; yine de çalıştı.

Temel fikir bir kez kaynak dizini tarar ve bunların kaynak dosyaları için bir dizi haritalama sınıfları oluşturur olmasıdır. Sınıfı, bir autoloader olarak kayıtlı ve çağrıldığında, bu gerekli dosyayı içerir. Bulunmazsa eğer, o anında diziyi yeniden çalışır.

/* register ClassLoader as class loader */
spl_autoload_register(array(ClassLoader::getInstance(), 'loadClass'));


class ClassLoader {

    private static $SAVE_FILE = 'ClassLoader.save.php';

    /* singleton */
    private static $instance;

    /* stores a className -> filePath map */
    private $classList;
    /* tells whether working from saved file */
    private $refreshed;


    public static function getInstance() {
        if (!isset(self::$instance)) {
            self::$instance = new ClassLoader();
        }
        return self::$instance;
    }

    private function __construct() {
        $this->initClassList();
    }

    public function loadClass($className) {
        if ( !array_key_exists($className, $this->classList) && !$this->refreshed ) {
            $this->refreshClassList();
        }
        require_once($this->classList[$className]);
    }

    private function initClassList() {
        if (file_exists(INCLUDES_DIR . self::$SAVE_FILE)) {
            require_once(INCLUDES_DIR . self::$SAVE_FILE);
            $this->refreshed = FALSE;
        } else {
            $this->refreshClassList();
        } 
    }

    private function refreshClassList() {
        $this->classList = $this->scanDirectory(INCLUDES_DIR);
        $this->refreshed = TRUE;

        $this->saveClassList();
    }

    private function saveClassList() {
        $handle = fopen(INCLUDES_DIR . self::$SAVE_FILE, 'w');
        fwrite($handle, "<?php\r\n");

        foreach($this->classList as $class => $path) {
            $line = '$this->classList' . "['" . $class . "'] = '" . $path . "';\r\n";
            fwrite($handle, $line);
        }

        fwrite($handle, '?>');
        fclose($handle);
    }

    private function scanDirectory ($directory) {
        // strip closing '/'
        if (substr($directory, -1) == '/') {
        	$directory = substr($directory, 0, -1);
        }

        if (!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) {
            return array();
        }

        $dirH = opendir($directory);
        $scanRes = array();

        while(($file = readdir($dirH)) !== FALSE) {

            // skip pointers
            if ( strcmp($file , '.') == 0 || strcmp($file , '..') == 0) {
                continue;
            }

            $path = $directory . '/' . $file;

            if (!is_readable($path)) {
                continue;
            }

            // recursion
            if (is_dir($path)) {
                $scanRes = array_merge($scanRes, $this->scanDirectory($path));

            } elseif (is_file($path)) {
                $className = explode('.', $file);
                if ( strcmp($className[1], 'class') == 0 && strcmp($className[2], 'php') == 0 ) {
                    $scanRes[$className[0]] = $path; 
                }
            }
        }

        return $scanRes;
    }

}

Ne yazık ki, açıkça her dizin eklemek zorunda. Bu ya özyinelemeli dizinleri erişir bir komut programlı yapılabilir, ya da bir listesini belirtebilirsiniz.

Muhtemelen en verimli şekilde dizinleri ve arama için alt dizin listesini belirlemek ve () ini_set kullanarak 'include_path' bu eklemektir.

Eğer karışık :) Ya da belki de ben senin soru tarafından karıştı görünüyor.

/ Kaç düzeyleri derin O nerede olduğunu sınıfını bulur ve yükler bir işlevi yazmak tamamen size kalmış, PHP umursamıyor.

Ve, SPL autoload too, bu aynı temel işlevselliğe sahiptir içine bakmak, ama birden özdevinimli_yükle fonksiyonları yazmak ve bunları zincir olabilir. Muhtemelen sizinki ile çelişebilir kendi autoloaders tanımlamak bazı dış kitaplıkları, kullanmak istiyorsanız, yararlı olabilir.

Eğer kendi fonksiyon konum ve sonra SPL ile kayıt bilgileri - Ben PHP'nin SPL özdevinimli_yükle yeteneği bahsediyoruz varsayalım.

Bunu nasıl size işlev (ler) içerir oluşturmak nasıl bağlıdır. Kaç size kalmış: Birden fazla fonksiyonları içerir ve daha sonra PHP ile bunları kayıt beyan etmek mümkündür. SPL özdevinimli_yükle yeteneği sadece kendi fonksiyonu oluşturmak ve sonra, her seferinde de dahil olmak üzere bir sınıf ihtiyaçlarını bu işlevi çalıştırmak için PHP söylemesini sağlar.

Birden yaratmanın bir yararı bunların kullanım için bunları kayıt yeteneği, en çok kullanılan dizin ilk azından son kullanılır. Bir dizin değiştirildi veya silindi Ayrıca, eğer, o zaman basit bir değişiklik ve / veya sorumlu silme fonksiyonu.

(Ben yönetim ve kod ayırmasının kolaylığı için bunu tavsiye etmem ama) çok tüm klasör yapısını konum geçeceği bir işlev yazabilirsiniz. Bunu yapmak için hiçbir "teknik olarak doğru" yolu vardır :)

Dizin geçişi ve adlandırılması bu hususlar parçası - Daha önce de belirttiğimiz gibi, SPL autoloading fonksiyonel, pratik uygulama greft zorunda üzerine bir yapıdır.

Zend Loader şeklinde pratik bir örneği ele alalım: onun temelinde, bu PHP yolunu içerir kayıtlı olan dizinlere ad ilişkilendirerek bir kuralını kullanır Bir tekiz. Pratik Örnek:

set_include_path(get_include_path(). PATH_SEPARATOR. 'App/'); //Concat the "App" directory onto the existing include paths
$loader = Zend_Loader::getInstance(); //because the autoloader is a singleton, we get a reference to it without assuming we need to first create it
$loader->registerNamespace('App_'); //Tell autoloader it can look in the app directory to find classes if it can't find them in the default Zend directory.

Açıkçası özel uygulama endişeleri projeden projeye değişir, ama içine özel bir sınıf biçimi (örn. 'directory_classname') ayrıştırmak bir autoloader programlama şansınızı denemek için, anlayış bir egzersiz olarak ve kodu tekrar kullanmak için, hem de iyi olabilir bir dizin harita, sonra yük ve sınıfını doğrulamak.