автоматически загрузитесь и несколько каталогов

Я думал, что это было о худшем комментарии ТАК сообщение и было разочаровано найти иначе.

12
задан 31 August 2009 в 19:00
поделиться

6 ответов

К сожалению, вам нужно явно добавить каждый каталог. Это можно сделать программно в сценарии, рекурсивно просматривающем ваши каталоги, или вы можете указать список.

Вероятно, наиболее эффективный способ - указать список каталогов и подкаталогов для поиска и добавить их в свой 'include_path' с помощью ini_set ().

1
ответ дан 2 December 2019 в 04:53
поделиться

Я предполагаю, что вы говорите о возможности автозагрузки PHP SPL - где вы пишете свою собственную функцию, а затем регистрируете ее с помощью SPL.

Как вы это делаете, зависит от того, как вы создаете включаемую функцию (ы). Можно объявить несколько включаемых функций, а затем зарегистрировать их с помощью PHP: сколько зависит от вас. Возможность автозагрузки SPL просто позволяет вам создать свою собственную функцию, а затем указать PHP запускать эту функцию каждый раз, когда требуется класс.

Одним из преимуществ создания нескольких является возможность регистрировать их в порядке их использования, наиболее часто используемом. каталог с первого до наименее используемого последним. Кроме того, если каталог изменен или удален, вы просто измените и / или удалите ответственную функцию.

Вы можете написать одну функцию, которая будет проходить через всю структуру вашей папки (хотя я бы не стал) Я рекомендую его для простоты администрирования и разделения кода). Не существует "технически правильного" способа сделать это :)

1
ответ дан 2 December 2019 в 04:53
поделиться

Кажется, вы сбиты с толку :) Или, может быть, ваш вопрос меня смущает.

Вы полностью должны написать функцию, которая находит и загружает класс, PHP не заботится, где /

И обратите внимание на автозагрузку SPL , она имеет ту же базовую функциональность, но вы можете написать несколько функций автозагрузки и затем связать их. Может быть полезно, если вы хотите использовать некоторые внешние библиотеки, которые определяют свои собственные автозагрузчики, которые могут конфликтовать с вашими.

1
ответ дан 2 December 2019 в 04:53
поделиться

Вот класс, который я написал некоторое время назад для аналогичной цели. В то время я все еще находился в стадии обучения, так что могли возникнуть глупые идеи; тем не менее, он работал.

Основная идея заключается в том, что он сканирует исходный каталог один раз и создает массив, отображающий классы в их исходные файлы. Класс регистрируется как автозагрузчик и при вызове включает в себя требуемый файл. Если он не найден, он пытается восстановить массив "на лету".

/* 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;
    }

}
10
ответ дан 2 December 2019 в 04:53
поделиться

Возможно, вы захотите взглянуть на Соглашение PEAR для имен классов, которое действительно отлично подходит для автозагрузки.

По сути, оно гласит:

Иерархия классов PEAR также отражено в названии класса, каждый уровень иерархии разделен одинарное подчеркивание.

Это означает, что найти файл для включения с именем класса HTML_Upload_Error - это просто вопрос замены '_' на '/'; предоставляя вам HTML / Upload / Error.php

Дополнительные объяснения и несколько примеров вы можете найти в статьях:

Кстати: это соглашение используется многими большими фреймворками / библиотеками ;-)
Например, Zend Framework использует это соглашение - и это действительно полезно!

17
ответ дан 2 December 2019 в 04:53
поделиться

Как уже упоминалось, автозагрузка SPL функционально является структурой, к которой вы должны привить практическую реализацию - обход каталога и соглашения об именах являются частью этих соображений.

Возьмем практический пример в форме загрузчика Zend: по своей сути это синглтон, использующий соглашение о сопоставлении пространств имен с каталогами, зарегистрированными с помощью пути включения PHP. Практический пример:

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.

Очевидно, что конкретные проблемы реализации будут варьироваться от проекта к проекту, но может быть лучше, как в качестве упражнения на понимание, так и для повторного использования кода, попробовать свои силы в программировании автозагрузчика, который может анализировать определенный формат класса ( например, 'имя_класса') в карту каталогов, затем загрузите и подтвердите класс.

1
ответ дан 2 December 2019 в 04:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: