如何在PHP中为多个目录使用spl_自动加载_寄存器?
实际上,我正在尝试为自己创建一个MVC框架,但是我在自动加载方面遇到了问题。实际上这不是问题,但我想问一下专家,当存在不同的目录时,他们是如何使用如何在PHP中为多个目录使用spl_自动加载_寄存器?,php,spl-autoload-register,Php,Spl Autoload Register,实际上,我正在尝试为自己创建一个MVC框架,但是我在自动加载方面遇到了问题。实际上这不是问题,但我想问一下专家,当存在不同的目录时,他们是如何使用spl\u autoload\u register功能的 假设我们有以下目录: Controllers Libs Models 每个文件夹包含不同的类,如: Controllers: Main.php File.php About.php Libs: Main.php Front_controller.php Model
spl\u autoload\u register
功能的
假设我们有以下目录:
Controllers
Libs
Models
每个文件夹包含不同的类,如:
Controllers:
Main.php
File.php
About.php
Libs:
Main.php
Front_controller.php
Models:
Index.php
File.php
Login.php
您可以注意到,在不同的目录中可能会找到一些同名的文件名。好的,到目前为止我已经试过了:
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 ;
}
});
它工作得很好,但是我相信还有另一种方法可以让一切变得更简单。有谁能建议我如何使这段代码更好或更简单/在这种情况下,大师们在使用什么
为了防止可能遇到此答案的个人获取过期信息,我已根据最新PSR自动加载标准对其进行了更新。出于历史目的和仅对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
最新答案
官方反对该标准,支持替代自动加载器。虽然两者在某些方面相似,但在其他方面也有很大不同。(例如:类名称中下划线的处理。)
你可能在想——“我现在使用PSR-0,它工作得很好。”事实是,PSR-0在某些项目上仍然工作得很好。当涉及到与不使用名称空间的包的向后兼容性时,尤其如此。PSR-0仍然是一个不错的自动加载原则,但它可以
当然,如果编程中有一件事是不变的,那就是代码最终会发生变化,编程技术也会不断发展。今天你可以帮自己一个忙,为明天做好准备。因此,如果您正在启动项目或试图将项目移植到可以使用命名空间的PHP的新版本,则应该认真考虑使用PSR4自动加载程序。
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
另外值得注意的是,如果您正在开发一个不使用名称空间的项目,那么PSR-4不适用于您。在这种情况下,PSR-0或您自己的自定义自动加载器适用
原始答案 如果您想在类中使用名称空间,那么路由是一种非常好的自动加载方式。基本上,名称空间表示目录结构,可以根据约定加载类 如果PSR-0方法不能满足您的所有需求(或者不能很好地处理现有代码),您仍然可以使用
spl\u autoload\u register
添加更多函数,PHP将逐一检查这些函数,以尝试加载类
用法示例:
首先,如果您不熟悉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.
对于您的登录
型号,您也会做同样的事情
<?php
namespace MyProject\Models;
class Login {
//Field vars, contructor, methods, etc. all go here.
}
?>
希望这有助于更好地理解它,同样,如果您不想使用名称空间,您可以始终将闭包添加到SPL自动加载堆栈中。如果需要,您可以在其中安装10个不同的自动加载器,PHP将使用每个函数逐个(按照您定义的顺序)检查它们,以尝试加载一个类。然而,一对夫妇的公约为基础的自动加载器是一个有点干净,更喜欢的方法。还要记住,自动加载程序将名称空间分隔符
\
和下划线\
转换为目录分隔符。因此,您的Front\u controller.php不会像您预期的那样自动加载。下面的代码会有所帮助。但我建议你检查名称空间
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;
}
}
});
这个问题已经在这里解决了。我已经看过了,但是我真的不知道应该如何实现示例代码。这对我来说并不是很明显。我已经更新了我的答案,以便更好地解释它。希望这对您有所帮助。@Crackertastic-感谢您提供了这个极好的示例。在对这个概念的修改中,我发现有必要修改类文件中的名称空间。例如,而不是名称空间MyProject\Models代码>,它不起作用,名称空间模型代码>确实有用。@knot22很高兴听到这个(旧的)示例仍在帮助其他人。快乐编码!不赞成。