像大多数Web开发人员一样,我非常享受固态MVC架构对Web应用程序和站点的好处.使用PHP进行MVC时,自动加载显然非常方便.
我已成为spl_autoload_register过度简单定义单个__autoload()函数的粉丝,因为如果要合并每个使用自己的自动加载的不同基本模块,这显然会更灵活.但是,我从来没有对我写的加载函数感到满意.它们涉及大量字符串检查和目录扫描,以便查找可能加载的类.
举例来说,假设我有一个具有被定义为基本路径的应用程序PATH_APP和一个简单的结构,命名的目录models,views和controllers.我经常使用命名结构来命名文件IndexView.php并IndexController.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;
}
Run Code Online (Sandbox Code Playgroud)
如果之后没有找到它,我可能有另一个函数来扫描models目录中的子目录.但是,所有if/else-ing,字符串检查和目录扫描对我来说似乎效率低下,我想改进它.
我很好奇其他开发人员可能采用的文件命名和自动加载策略.我正在寻找专门用于高效自动加载的良好技术,而不是自动加载的替代方案.
我试图利用PHP中的自动加载.我在不同的目录中有各种类,所以我已经引导自动加载如下:
function autoload_services($class_name)
{
$file = 'services/' . $class_name. '.php';
if (file_exists($file))
{
require_once($file);
}
}
function autoload_vos($class_name)
{
$file = 'vos/' . $class_name. '.php';
if (file_exists($file))
{
require_once($file);
}
}
function autoload_printers($class_name)
{
$file = 'printers' . $class_name. '.php';
if (file_exists($file))
{
require_once($file);
}
}
spl_autoload_register('autoload_services');
spl_autoload_register('autoload_vos');
spl_autoload_register('autoload_printers');
Run Code Online (Sandbox Code Playgroud)
这一切似乎都很好,但我只想仔细检查这确实被认为是可以接受的做法.
class Manage
{
spl_autoload_register(function($class) {
include $class . '.class.php';
});
}
Run Code Online (Sandbox Code Playgroud)
说我有一些像上面这样的代码.我选择使用加载类的匿名函数方法,但这是如何使用的?它究竟是如何确定'$class'要加载的?
我实际上是在尝试为自己创建一个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)
它运作良好,但我确信还有另一种方法可以使一切变得更简单.任何人都可以建议我如何使这些代码更好或更简单/在这种情况下大师使用什么?
我的命名空间中的自动加载有点问题.如PHP手册所示:http://us.php.net/manual/en/language.namespaces.rules.php您应该能够使用完全限定名称自动加载命名空间函数,例如\ glue\common\is_email( ).
事情是我有一个函数spl_autoload_register(array($ import,"load")); 在初始命名空间内,但每当我尝试从初始命名空间调用\ glue\common\is_email()时,它都不会传递自动加载功能,但是当使用新的is_email()时(在类的上下文中)它将会.我不明白手册说我可以从完全合格的名字自动加载,但我不能:.
这是我的代码:
namespace glue;
require_once 'import.php';
use glue\import as import;
use glue\core\router as router;
$import = new import();
spl_autoload_register(array($import, "load"));
/** Works and echos glue\router **/
$router = new router();
/** Don't do nothing **/
$cheese = \glue\common\is_email($email);
Run Code Online (Sandbox Code Playgroud)
我也试过这段代码:
namespace glue;
require_once 'import.php';
use glue\import as import;
use glue\core\router as router;
use glue\common;
$import = new import();
spl_autoload_register(array($import, "load"));
/** Works and echos glue\router **/
$router = new router();
/** …Run Code Online (Sandbox Code Playgroud) 经过一些研究,无法找到解决问题的方法.我正在使用API,这是我通过composer下载的命名空间.API让它依赖于我允许作曲家为我管理和自动加载.与此分开,我有大约10个类,我已经使用php自动加载spl_autoload_register.最近,我开始混合这些类来完成一个项目的部分,整个事情已经变成了废话.我的自定义类不能使用作曲家类,反之亦然.有没有一种方法可以用来自动加载两个独立文件夹中的类,并加载两个独立的外载程序.
这是我目前使用的代码.vender/autoload.php与典型的作曲家自动加载器没有什么不同.谢谢你的帮助.
require 'vendor/autoload.php';
require 'functions/general.php';
require 'include/mailgun.php';
function my_autoloader($class) {
require 'classes/' . $class . '.php';
}
spl_autoload_register('my_autoloader');
Run Code Online (Sandbox Code Playgroud) 我正在开发自定义框架.当我试图动态调用我的类时,我遇到了一个问题.
这是我的文件的视觉效果:

所以我决定为每个文件夹(libs,controllers和modeles)创建一个不同的函数:
function autoloadLibs($class) {
//require the general classes
require 'libs/' . $class . '.php';
}
function autoloadModels($class) {
//require the models classes
require 'models/' . $class . '.php';
}
function autoloadControllers($class) {
//require the controllers classes
require 'controllers/' . $class . '.php';
}
spl_autoload_register ('autoloadLibs');
spl_autoload_register ('autoloadControllers');
spl_autoload_register ('autoloadModels');
Run Code Online (Sandbox Code Playgroud)
不过我有这样的消息:警告:require(libs/admin.php):无法打开流,cours它不是好文件夹.但我不知道如何解决这个问题.有没有一种优化我的类调用的好方法?
我让spl_autoload_register工作正常,但后来我决定添加一些命名空间来引入PSR2,并且似乎无法使其正常工作.
目录结构:
-index.php
-classes/
-Class1.class.php
-Class2.class.php
-Class3.class.php
Run Code Online (Sandbox Code Playgroud)
每节课都以:
namespace Foo;
Class ClassX {
Run Code Online (Sandbox Code Playgroud)
index.php文件:
<?php
spl_autoload_register(function($class) {
include 'classes/' . $class . '.class.php';
});
$myObj = new Class1();
echo $myObj->doSomething();
Run Code Online (Sandbox Code Playgroud)
这个产品出错了 Fatal error: Class 'Class1' not found in /var/www/myApp/index.php on line X
我的第一个想法是我需要在我的实例化中使用命名空间,所以我改为index.php:
$myObj = new Foo\Class1();
Run Code Online (Sandbox Code Playgroud)
但是,我得到了
Warning: include(classes/Foo\Class1.class.php): failed to open stream: No such file or directory in /var/www/myApp/index.php on line 6
如果我做手动包括一切正常,include 'classes/Class1.class.php';等等.
根据PHP页面上的最高评论spl_autoload_register( ):
对于具有命名空间类的PHP 5.3用户来说是个好消息:
当您创建与包含类的名称空间匹配的子文件夹结构时,您甚至不必定义自动加载器.
<?php
spl_autoload_extensions(".php"); // comma-separated list
spl_autoload_register();
?>
Run Code Online (Sandbox Code Playgroud)
但是,当我有以下结构时:
* classes/someclass.php
* index.php
其中someclass.php包含以下内容:
<?php
class someclass {
function __construct( ) {
echo 'It works!';
}
}
?>
Run Code Online (Sandbox Code Playgroud)
并index.php包含:
<?php
spl_autoload_extensions(".php");
spl_autoload_register();
new classes\someclass;
?>
Run Code Online (Sandbox Code Playgroud)
然后我收到以下错误:
致命错误:spl_autoload():无法加载类classes\someclass
我弄错了吗?我怎样才能做到这一点?
从评论
这对于班级不起作用:
<?php
namespace classes;
class someclass {
function __construct( ) {
echo 'It works!';
}
}
?>
Run Code Online (Sandbox Code Playgroud) 我是这个命名空间的新手.
我在我的基本目录2类(单独的文件),说class1.php和class2.php一个目录中src/.
class1.php
namespace \src\utility\Timer;
class Timer{
public static function somefunction(){
}
}
Run Code Online (Sandbox Code Playgroud)
class2.php
namespace \src\utility\Verification;
use Timer;
class Verification{
Timer::somefunction();
}
Run Code Online (Sandbox Code Playgroud)
当我执行时class2.php,我得到致命错误
PHP致命错误:在路径//class2.php中找不到类'Timer'在第***行
我在某处看过,我需要为此创建自动加载器.如果是这样,我该如何创建一个,如果没有,那么还有什么问题呢?
UPDATE
我创建了一个Autoloader,它将require所有必需的文件放在我的PHP脚本之上.所以,现在class2.php会像这样结束.
namespace \src\utility\Verification;
require '/path/to/class1.php'
use Timer;
//or use src\utility\Timer ... both doesn't work.
class Verification{
Timer::somefunction();
}
Run Code Online (Sandbox Code Playgroud)
这也行不通,它表明找不到类.但是,如果我删除了所有的namespaces,那use就是.一切正常.