如何在PHP中使用spl_autoload_register用于多个处理器?

Rad*_*ity 18 php spl-autoload-register

我实际上是在尝试为自己创建一个MVC框架,但是我在使用Autoload时遇到了麻烦.实际上这不是问题,但我想问一下大师们,spl_autoload_register当有不同的目录时,他们如何使用该功能.

可以说我们有以下目录:

Controllers
Libs
Models
Run Code Online (Sandbox Code Playgroud)

每个文件夹包含不同的类,如:

Controllers:
   Main.php
   File.php
   About.php
Libs:
   Main.php
   Front_controller.php
Models:
   Index.php
   File.php
   Login.php
Run Code Online (Sandbox Code Playgroud)

您可以注意到,在不同的目录中可能会找到一些具有相同名称的文件名.好的,所以这是我到目前为止所尝试的:

spl_autoload_register(function ($class) { 

    $pathContorllers = 'Controllers/' . $class . '.php';
    $pathLibs = 'Libs/' . $class . '.php';
    $pathModels = 'Models/' . $class . '.php';

    if (file_exists($pathContorllers)) {
        require_once $pathContorllers;
    } elseif (file_exists($pathLibs)) {
        require_once $pathLibs;
    } elseif (file_exists($pathModels )) {
        require_once $pathModels ;
    }
});
Run Code Online (Sandbox Code Playgroud)

它运作良好,但我确信还有另一种方法可以使一切变得更简单.任何人都可以建议我如何使这些代码更好或更简单/在这种情况下大师使用什么?

Cra*_*tic 34

为了使可能遇到此答案的人员获得过时信息,我已根据最新的PSR自动加载标准对其进行了更新.原始答案已经保留用于历史目的以及仅对PSR-0自动装载机感兴趣的人.

更新的答案

PHP-图已经正式弃用的PSR-0赞成替代自动加载机的标准,PSR-4 .尽管两者在某些方面相似但在其他方面也非常不同.(例如:在类名中处理下划线.)

你可能会想到自己 - "我现在使用PSR-0并且工作正常." 问题的真相是,PSR-0对于某些项目仍然可以正常工作.当涉及不使用命名空间的包的向后兼容性时尤其如此.PSR-0仍然是一个不错的自动加载原则,但它有其自身的缺点.

当然,如果编程中存在一个常数,那就是代码最终会发生变化,编程技术也会不断发展.今天你可以为明天做好准备,帮助自己.因此,如果您刚刚启动项目或尝试将项目移植到可以使用命名空间的较新版本的PHP,则应认真考虑使用PSR-4自动加载器.

值得注意的是,如果您正在开发一个不使用命名空间的项目,那么PSR-4不适用于您.在这种情况下,PSR-0或您自己的自定义自动加载器适用.


原始答案

如果你想在你的类中使用命名空间,那么PSR-0路由是一种非常好的自动加载方式.基本上,您的命名空间表示您的目录结构,并且可以根据约定加载类.

如果PSR-0方法不能满足您的所有需求(或者不能很好地使用现有代码),您仍然可以添加更多函数,spl_autoload_registerPHP将逐个尝试加载类.

用法示例:

首先,如果您不熟悉PHP中的命名空间,那么您将从检查该主题的PHP手册中受益.起初它们可能有点令人困惑,但它们的好处值得最初的困惑.

所以我说PSR-0的工作原理是将名称空间与目录结构相关联.我们以你的目录为例.您在根文件夹中(无论它在哪里)具有以下内容:

Project directory:  <- Let's call this directory "MyProject"
    Controllers:
       Main.php
       File.php
       About.php
    Libs:
       Main.php
       Front_controller.php
    Models:
       Index.php
       File.php
       Login.php
index.php <- Let's say this is your entry point file, this is where you will be autoloading stuff from.
Run Code Online (Sandbox Code Playgroud)

现在让我们来看看你的控制器Main.php.需要记住的两件事是类名需要是文件的名称,该类的名称空间是该文件的目录路径.所以Main.php应该看起来像这样:

<?php

namespace MyProject\Controllers;

class Main {

    //Field vars, contructor, methods, etc. all go here.

}

?>
Run Code Online (Sandbox Code Playgroud)

你会为你的Login模型做同样的事情

<?php

namespace MyProject\Models;

class Login {

    //Field vars, contructor, methods, etc. all go here.

}

?>
Run Code Online (Sandbox Code Playgroud)

现在在你的index.php文件中(在根目录中) - MyProject你会打电话spl_autoload_register给它并给它PSR-0自动加载器.

spl_autoload_register( function ($className) {
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
});

//Now you can make your call to your objects without a bunch of include/require statements

$main = new \MyProject\Controllers\Main();  //Instantiates your 'Main' controller
$login = new \MyProject\Models\Login();   //Instantiates your 'Login' model
Run Code Online (Sandbox Code Playgroud)

希望这有助于更好地理解它,再次,如果您不想使用命名空间,您可以始终只是在SPL自动加载堆栈中添加闭包.如果需要,你可以在那里拥有10个不同的自动加载器,PHP将逐个使用它们(按照你定义它们的顺序),尝试加载一个类.但是,一些基于会议的自动加载器更清洁,更像是一种首选方法.另请注意,自动加载器会将命名空间分隔符\和下划线都转换_为目录分隔符.所以你Front_controller.php不会像你期望的那样自动加载.


use*_*950 9

以下代码将有所帮助.但我建议你查看命名空间.

spl_autoload_register ( function ($class) {

$sources = array("Controllers/$class.php", "Lib/$class.php ",  "Models/$class.php " );

    foreach ($sources as $source) {
        if (file_exists($source)) {
            require_once $source;
        } 
    } 
});
Run Code Online (Sandbox Code Playgroud)