Сведения о вопросе

Fedya

18:57, 28th August, 2020

Теги

php   class   include   autoload    

Как обрабатывать в том числе необходимые классы в PHP

Просмотров: 477   Ответов: 7

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

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

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

Есть ли более простой способ справиться с этим?

Или PHP просто не подходит для приложений типа "enterprisey" с большим количеством различных объектов, расположенных в отдельных файлах, которые могут находиться во многих разных каталогах.



  Сведения об ответе

ITSME

03:23, 22nd August, 2020

I Мои приложения обычно имеют файл setup.php , который включает в себя все основные классы (т. е. фреймворк и сопутствующие библиотеки). Мои пользовательские классы загружаются с помощью autoloader с помощью карты расположения каталогов.

Каждый раз, когда добавляется новый класс, я запускаю скрипт командной строки builder, который сканирует все дерево каталогов в поисках классов моделей, а затем строит ассоциативный массив с именами классов в качестве ключей и путями в качестве значений. Затем функция _ _ autoload ищет имя класса в этом массиве и получает include path. Вот этот код:

autobuild.php

define('MAP', 'var/cache/autoload.map');
error_reporting(E_ALL);
require 'setup.php';
print(buildAutoloaderMap() . " classes mapped\n");

function buildAutoloaderMap() {
    $dirs = array('lib', 'view', 'model');
    $cache = array();
    $n = 0;
    foreach ($dirs as $dir) {
        foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)) as $entry) {
            $fn = $entry->getFilename();
            if (!preg_match('/\.class\.php$/', $fn))
                continue;
            $c = str_replace('.class.php', '', $fn);
            if (!class_exists($c)) {
                $cache[$c] = ($pn = $entry->getPathname());
                ++$n;
            }
        }
    }
    ksort($cache);
    file_put_contents(MAP, serialize($cache));
    return $n;
}

autoload.php

define('MAP', 'var/cache/autoload.map');

function __autoload($className) {
    static $map;
    $map or ($map = unserialize(file_get_contents(MAP)));
    $fn = array_key_exists($className, $map) ? $map[$className] : null;
    if ($fn and file_exists($fn)) {
        include $fn;
        unset($map[$className]);
    }
}

Обратите внимание, что соглашение об именовании файлов должно быть [class_name].class.php. Изменить каталоги классов будет выглядеть в autobuild.php . Вы также можете запустить autobuilder из функции autoload, когда класс не найден, но это может привести вашу программу в бесконечный цикл.

Сериализованные массивы чертовски быстры.

@JasonMichael: PHP 4 мертв. Получить над ним.


  Сведения об ответе

SKY

13:28, 16th August, 2020

Вы можете определить несколько функций автоматической загрузки с помощью spl_autoload_register:

spl_autoload_register('load_controllers');
spl_autoload_register('load_models');

function load_models($class){
    if( !file_exists("models/$class.php") )
        return false;

    include "models/$class.php";
    return true;
}
function load_controllers($class){
    if( !file_exists("controllers/$class.php") )
        return false;

    include "controllers/$class.php";
    return true;
}


  Сведения об ответе

прога

09:19, 27th August, 2020

Вы также можете программно определить местоположение файла класса с помощью структурированных соглашений об именовании, которые сопоставляются с физическими каталогами. Вот как Zend делает это в рамках Zend Framework . Поэтому, когда вы вызываете Zend_Loader::loadClass("Zend_Db_Table"); , он взрывает имя класса в массив каталогов, разбивая его на подчеркивания, а затем класс Zend_Loader загружает требуемый файл.

Как и все модули Zend, я ожидал бы, что вы можете использовать только загрузчик сам по себе с вашими собственными классами, но я использовал его только как часть сайта, использующего zend's MVC.

Но были опасения по поводу производительности под нагрузкой, когда вы используете любой вид динамической загрузки классов, например, смотрите этот пост в блоге , сравнивая Zend_Loader с жесткой загрузкой файлов классов.

Помимо снижения производительности при поиске по пути PHP include, это приводит к отказу от кэширования кода операции. Из комментария к этому посту:

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


  Сведения об ответе

Chhiki

10:03, 23rd August, 2020

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

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


  Сведения об ответе

repe

23:22, 5th August, 2020

__autoload будет работать, но только в PHP 5.


  Сведения об ответе

FAriza

15:44, 15th August, 2020

Из всех предложений до сих пор я неравнодушен к Кевину, но это не обязательно должно быть абсолютным. Я вижу несколько различных вариантов использования с _ _ autoload.

  1. Поместите все файлы класса в один каталог. Назовите файл После класса, т. е. classes/User.php или classes/User.class.php .
  2. Идея Кевина поместить модели в один каталог, контроллеры в другой и т. д. Хорошо работает, если все ваши классы хорошо вписываются в рамки MVC, но иногда все становится запутанным.
  3. Включите каталог в имя класса. Например, класс с именем Model_User на самом деле будет располагаться в classes/Model/User.php . Ваша функция _ _ autoload будет знать, как перевести символ подчеркивания в разделитель каталогов, чтобы найти файл.
  4. Просто проанализируйте всю структуру каталогов один раз. Либо в функции __autoload, либо даже просто в том же файле PHP, где он определен, выполните цикл над содержимым каталога classes и кэшируйте, какие файлы находятся там. Таким образом, если вы попытаетесь загрузить класс User , не имеет значения, находится ли он в classes/User.php , classes/Models/User.php или classes/Utility/User.php . Как только он найдет User.php где-то в каталоге classes , он будет знать, какой файл включать, когда класс User должен быть загружен автоматически.


  Сведения об ответе

COOL

15:12, 7th August, 2020

@Kevin:

Я просто пытался указать, что spl_autoload_register является лучшей альтернативой _ _ autoload, так как вы можете определить несколько загрузчиков, и они не будут конфликтовать друг с другом. Удобно, если вам нужно включить библиотеки, которые также определяют функцию _ _ autoload.

- Вы уверены? В документации говорится иначе:

Если в коде есть существующая функция _ _ autoload, то эта функция должна быть явно зарегистрирована в стеке _ _ autoload. Это происходит потому, что spl_autoload_register() эффективно заменит кэш ядра для функции _ _ autoload либо на spl_autoload(), либо на spl_autoload_call().

=> вы также должны явно зарегистрировать __autoload любой библиотеки. Но помимо этого вы, конечно, правы, эта функция является лучшей альтернативой.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться