How can I load classes from multiple directories with __autoload?

試著忘記壹切 提交于 2019-12-04 13:42:58

You can register multiple autoload functions by using spl_autoload_register instead of the single __autoload function. That's the recommended way.

If one autoloader was able to load the file, the next one in the stack won't be called.

Each autoloader however should only load the classes it is for, so you need to check that by the classname and/or with is_file. By classname often is better because trying wildly on the file-system can stress a system if your application grows.

To not re-invent the wheel, you could even use an autoloader that already exists which is able to deal with the PSR-0 standard on file-name-calling. Those often allow to register a specific namespace on a base-directory. In your case that would mean that you must rename and organize your files according to the PSR-0 convention.


The quick solution (bound to your question):

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

As you can see, there is already code duplicated (as in yours). So this should just be a temporary solution as you will end up with more and more duplicated lines for each directory you would like to test for. If you consider to change the design, please take the PSR-0 shema into account, it helps to streamline one's codebase and makes it easy to re-use other existing compontents in the PHP world.


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');

Follow PSR-0

The correct way to do this is to adopt the PSR-0 naming convention, and then to use a PSR-0 compatible autoloader, such as the UniversalClassLoader from Symfony2's ClassLoader component.

For example:

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
}

The symfony ClassLoader is in 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();

What this does, in essence, is use spl_register_autoload to register an autoloader which tries to match the requested classes against all registered paths, if one matches, it is required. Otherwise the autoloader will continue searching.

So what your bootstrap code does is include autoload.php, after that all other classes will be autoloaded.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!