高效的PHP自动加载和命名策略

uqjltbpv  于 2023-04-28  发布在  PHP
关注(0)|答案(4)|浏览(111)

像现在大多数Web开发人员一样,我非常享受Web应用程序和网站的可靠MVC架构的好处。当使用PHP进行MVC时,自动加载显然非常方便。
我已经成为spl_autoload_register的粉丝,而不是简单地定义一个__autoload()函数,因为如果你合并了不同的基本模块,每个模块都使用自己的自动加载,这显然更灵活。然而,我从来没有对我写的加载函数感觉很好。它们涉及到大量的字符串检查和目录扫描,以便查找可能要加载的类。
例如,假设我有一个应用程序,它的基路径定义为PATH_APP,以及一个简单的结构,目录名为modelsviewscontrollers。我经常使用一种命名结构,即在适当的目录中将文件命名为IndexView.phpIndexController.php,默认情况下,模型通常没有特定的方案。我可能有一个类似这样的结构的加载器函数,它被注册到spl_autoload_register

public function MVCLoader($class)
{
    if (file_exists(PATH_APP.'/models/'.$class.'.php')) {
        require_once(PATH_APP.'/models/'.$class.'.php');
        return true;
    }
    else if (strpos($class,'View') !== false) {
        if (file_exists(PATH_APP.'/views/'.$class.'.php')) {
            require_once(PATH_APP.'/views/'.$class.'.php');
            return true;
        }
    }
    else if (strpos($class,'Controller') !== false) {
        if (file_exists(PATH_APP.'/controllers/'.$class.'.php')) {
            require_once(PATH_APP.'/controllers/'.$class.'.php');
            return true;
        }
    }
    return false;
}

如果在那之后没有找到它,我可能有另一个函数来扫描models目录中的子目录。然而,所有的if/else-ing,字符串检查和目录扫描对我来说似乎效率很低,我想改进它。
我很好奇其他开发人员会采用什么样的文件命名和自动加载策略。我特别寻找好的技术来有效地使用自动加载,而不是自动加载的替代品。

m4pnthwp

m4pnthwp1#

这是我在所有项目中一直使用的内容(直接从上一个项目的来源):

public static function loadClass($class)
{
    $files = array(
        $class . '.php',
        str_replace('_', '/', $class) . '.php',
    );
    foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $base_path)
    {
        foreach ($files as $file)
        {
            $path = "$base_path/$file";
            if (file_exists($path) && is_readable($path))
            {
                include_once $path;
                return;
            }
        }
    }
}

如果我查找SomeClass_SeperatedWith_Underscores,它将查找SomeClass_SeperatedWith_Underscores。php后跟SomeClass/SeperatedWith/Underscores。php在当前include路径中的每个目录中根。

**编辑:**我只是想说明,我使用这个是为了提高开发效率,而不一定是处理时间。如果你的路径上有PEAR,那么有了它,你就可以只使用这些类,而不必在需要的时候包含它们。

我倾向于将类保持在目录层次结构中,用下划线分隔命名空间。..如果我愿意,这段代码可以让我保持文件结构的整洁,或者如果我愿意,可以注入一个没有嵌套目录的快速类文件(用于向库添加一个或两个类,它是被告,但不是我目前正在工作的项目的一部分。)

4dbbbstv

4dbbbstv2#

我找到了这个解决方案:
我创建了一个脚本,它遍历我的类库文件夹(其中包含独立模块/系统的子文件夹),并解析文件内容以查找类定义。如果它在php文件中找到一个类定义(非常简单的正则表达式模式),它会创建一个符号链接:

class_name.php -> actual/source/file.php

这使我可以使用一个简单的自动加载函数,它只需要类名和主符号链接文件夹的路径,而不必进行任何路径/字符串操作。
最好的部分是,我可以重新安排我的源代码完全或添加一个新的子系统,只需运行链接生成脚本有一切自动加载。

nkhmeac6

nkhmeac63#

如果你想要效率,那么你根本不应该使用自动加载功能。自动加载功能是为了偷懒。在包含包含文件时,应提供包含文件的显式路径。如果您的自动加载函数可以找到这些文件,那么您可以编写代码来显式地找到它们。当你正在处理代码的视图部分,并准备加载一个新的视图类时,通过让autoload函数处理它,它首先假设你的类是一个模型类?这是没有效率的。你的代码应该是:

include_once $this->views_path . $class . '.php';

如果你需要多个“视图”路径,请创建一个加载视图的函数:

public function load_view($class) {
    // perhaps there's a mapping here instead....
    foreach ($this->views_paths as $path) {
        $filename = $path . $class . '.php';
        if (file_exists($filename)) {
            include_once $filename;
        }
    }
    throw ....
}

在任何情况下,在包含发生的地方,你有关于你想要加载的类的最大/最准确的信息。使用该信息完全加载类是唯一有效的类加载策略。是的,你可能会得到更多的类变量或者(但愿不会)一些全局变量。但这比懒惰和为类扫描文件系统的一部分要好。

8iwquhpp

8iwquhpp4#

PSR-4是由PHP标准推荐(PSR)定义的标准,它提供了一种一致的、可互操作的自动加载类的方法。在PSR-4自动加载中,您定义了类的名称空间和它在文件系统上的位置之间的Map。Composer包管理器在生成vendor/autoload.php文件时默认实现此标准。您可以包含此文件并开始使用这些库提供的类,而无需任何额外的工作:

require __DIR__ . '/vendor/autoload.php';

$log = new Monolog\Logger('name');
$log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING));
$log->warning('Foo');

您甚至可以通过向composer.json添加一个autoload字段来向autoloader添加您自己的代码。

{
    "autoload": {
        "psr-4": {"Acme\\": "src/"}
    }
}

参考: www.example.com

相关问题