Как я могу загрузить классы из нескольких каталогов с помощью __autoload? - PullRequest
3 голосов
/ 10 октября 2011

В ответ на этот вопрос кажется, что проблему с дубликатами можно решить, просто воспользовавшись приведенным ниже кодом __autoload,

function __autoload($class_name) 
{
    include AP_SITE."classes_1/class_".$class_name.".php";
}

$connection = new database_pdo(DSN,DB_USER,DB_PASS);
var_dump($connection);

результат,

object(database_pdo)[1]
  protected 'connection' => 
    object(PDO)[2]

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

function __autoload($class_name) 
{
    include AP_SITE."classes_1/class_".$class_name.".php";
    include AP_SITE."classes_2/class_".$class_name.".php";
}

Сообщение * * 1013

Внимание: включают в себя (С: /wamp/www/art_on_your_doorstep_2011_MVC/global/applications/CART/classes_2/class_database_pdo.php) [function.include]: не удалось открыть поток: нет такого файла или каталога в ...

которая ссылается на эту строку - include AP_SITE."classes_2/class_".$class_name.".php";

Итак, мой вопрос - как я могу загрузить классы из нескольких каталогов с помощью __autoload?

возможное решение:

function autoload_class_multiple_directory($class_name) 
{

    # List all the class directories in the array.
    $array_paths = array(
        'classes_1/', 
        'classes_2/'
    );

    # Count the total item in the array.
    $total_paths = count($array_paths);

    # Set the class file name.
    $file_name = 'class_'.strtolower($class_name).'.php';

    # Loop the array.
    for ($i = 0; $i < $total_paths; $i++) 
    {
        if(file_exists(AP_SITE.$array_paths[$i].$file_name)) 
        {
            include_once AP_SITE.$array_paths[$i].$file_name;
        } 
    }
}

spl_autoload_register('autoload_class_multiple_directory');

Ответы [ 2 ]

5 голосов
/ 10 октября 2011

Вы можете зарегистрировать несколько функций автозагрузки, используя spl_autoload_register вместо одной функции __autoload. Это рекомендуемый способ.

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

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

Чтобы не изобретать велосипед, вы могли бы даже использовать уже существующий автозагрузчик, способный работать со стандартом PSR-0 при вызове имени файла. Они часто позволяют зарегистрировать определенное пространство имен в базовом каталоге. В вашем случае это будет означать, что вы должны переименовать и упорядочить файлы в соответствии с соглашением PSR-0 .


Быстрое решение (связано с вашим вопросом):

function __autoload($class_name) 
{
    $file = sprintf('%sclasses_1/class_%s.php', AP_SITE, $class_name);
    if (is_file($file))
    {
        include $file;
        return;
    }
    $file = sprintf('%sclasses_2/class_%s.php', AP_SITE, $class_name);
    if (is_file($file))
    {
        include $file;
        return;
    }
}

Как видите, уже есть дублированный код (как у вас). Так что это должно быть только временное решение, так как вы получите все больше и больше дублированных строк для каждого каталога, для которого вы хотите проверить. Если вы решите изменить дизайн, пожалуйста, примите во внимание схему PSR-0, она помогает упростить базу кода и упростить повторное использование других существующих компонентов в мире PHP.


function autoload_class_multiple_directory($class_name) 
{

    # List all the class directories in the array.
    $array_paths = array(
        'classes_1/', 
        'classes_2/'
    );

    foreach($array_paths as $path)
    {
        $file = sprintf('%s%s/class_%s.php', AP_SITE, $path, $class_name);
        if(is_file($file)) 
        {
            include_once $file;
        } 

    }
}

spl_autoload_register('autoload_class_multiple_directory');
2 голосов
/ 10 октября 2011

Следуйте PSR-0

Правильный способ сделать это - принять соглашение о присвоении имен PSR-0 , а затем использовать PSR-0-совместимый автозагрузчик, такой как UniversalClassLoader из компонента Symfony2 * ClassLoader .

Например:

a / src / ProjectA / Database / Pdo.php :

<?php

namespace ProjectA\Database;

class Pdo
{
    // your code
}

b / src / ProjectB / Mail / Smtp.php :

<?php

namespace ProjectB\Mail;

class Smtp
{
    // your code
}

Загрузчик классов Symfony находится в vendor/symfony/src/Symfony/Component/ClassLoader.

autoload.php :

<?php

require __DIR__.'/vendor/symfony/src/Symfony/Component/ClassLoader';

use Symfony\Component\ClassLoader\UniversalClassLoader;

$loader = new UniversalClassLoader();
$loader->registerNamespace('ProjectA', __DIR__.'/a/src');
$loader->registerNamespace('ProjectB', __DIR__.'/b/src');
$loader->register();

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

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

...