我一直在尝试使用自动加载器类目录映射技术,这有点麻烦。我设法提出了一个非常简单的解决方案(从表面上看),但是我完全怀疑它完全可以工作,而其他“更明显”的解决方案却失败了。下面是一些代码片段,它们说明了我的困惑。
这是工作代码:
<?php
spl_autoload_register('my_autoloader');
function my_autoloader($class) {
$classMap = array(
'classes/',
'classes/sites/',
'classes/data/'
);
foreach ($classMap as $location) {
if (!@include_once($location . $class . '.php')) { // @ SUPPRESSES include_once WARNINGS
// CLASS DOESN'T EXIST IN THIS DIRECTORY
continue;
} else {
// CLASS IS AUTO-LOADED
break;
}
}
}
?>
这是我认为应该可以使用的代码段,但无效:
<?php
spl_autoload_register('my_autoloader');
function my_autoloader($class) {
$classMap = array(
'classes/',
'classes/sites/',
'classes/data/'
);
foreach ($classMap as $location) {
if (file_exists($location . $class . '.php')) {
require_once ($location . $class . '.php');
}
}
}
?>
后者对我来说更有意义,因为尽管这两个版本都可以工作:
<?php
spl_autoload_register('my_autoloader');
function my_autoloader($class) {
require_once ('classes/sites/' . $class . '.php');
}
?>
<?php
spl_autoload_register('my_autoloader');
function my_autoloader($class) {
$location = 'classes/sites/';
require_once ($location . $class . '.php');
}
?>
这会抛出“没有这样的文件或目录...”(请注意,路径中缺少“sites/”。
<?php
spl_autoload_register('my_autoloader');
function my_autoloader($class) {
require_once ('classes/' . $class . '.php');
}
?>
“没有这样的文件或目录...”错误使我觉得我可以简单地检查一个类的支持文件,如果(file_exists()){require_once(); break;} else {continue;}
为什么不起作用?而且,为什么第一个片段起作用了?支持路径/文件永远不会明确包含或不需要。
最佳答案
好,我知道了。我的问题确实是没有正确设置路径。使用__DIR__
常量是:: ahem::的成功之路。这是我现在正在使用的工作代码:
<?php
spl_autoload_register('my_autoloader');
function my_autoloader($class) {
$classMap = array(
'classes/',
'classes/sites/',
'classes/data/'
);
foreach ($classMap as $location) {
if (file_exists(__DIR__ . '/' . $location . $class . '.php')) {
require_once(__DIR__ . '/' . $location . $class . '.php');
break;
}
}
}
?>
事实证明,
__DIR__
返回实际文件所在的目录位置(而不是包含它的文件),这意味着只要该文件保留在目录的根目录中,它就可以工作。我的/classes目录。而且,它专门用于定义此类设置...希望这可以帮助其他人!而且,当然,如果任何人都可以阐明为什么该解决方案不是最优的,那么我全都注视着……
编辑:我将执行的一种优化是将$ classMap array()转换为关联数组(例如,
$classMap = array('root' => 'classes/', 'sites' => 'classes/sites/');
,这样我可以进行查找,而不是遍历我创建的所有目录。但是,我想那是另一个线程。EDIT2 :如果有人感兴趣,这是我想到的作为关联数组进行操作的解决方案。基本上,我在$ GLOBALS中设置了一个关联数组,并使用它来存储Classes-> Packages的映射。然后,在自动加载器中,我映射Packages-> Locations,然后调用实例化类所需的文件。
这是全局配置文件:
<?php
// INITIALIZE GLOBAL Class -> Package map
if (!array_key_exists('packageMap',$GLOBALS)) {
$GLOBALS['packageMap'] = array();
}
spl_autoload_register('my_autoloader');
function my_autoloader($class) {
$classMap = array(
'root'=>'/classes/',
'sites'=>'/classes/sites/',
'data'=>'/classes/data/'
);
// RESOLVE MAPPINGS TO AN ACTUAL LOCATION
$classPackage = $GLOBALS['packageMap'][$class];
$location = $classMap[$classPackage];
if (file_exists(__DIR__ . $location . $class . '.php')) {
require_once(__DIR__ . $location . $class . '.php');
}
}
?>
这是使用自动加载器的特定站点配置文件:
<?php
// LOAD GLOBAL CONFIG FILE
require_once('../config/init.php');
// CREATE LOCAL REFERENCE TO GLOBAL PACKAGE MAP (MOSTLY FOR READABILITY)
$packageMap = $GLOBALS['packageMap'];
// ADD Class -> Package MAPPINGS
$packageMap['DAO'] = 'data';
$packageMap['SomeSite'] = 'sites';
$packageMap['PDOQuery'] = 'data';
// INSTANTIATE SOMETHING IN ONE OF THE PACKAGES
$someSite = new SomeSite();
?>
希望这对其他人有用...如果它对任何人都发出了红旗,请发出提示。最终,我想用$ apc代替$ GLOBALS的使用,但是它没有安装在我的托管服务器上:/。我可能会考虑使用memcached,但听过好坏参半的评价...
关于PHP自动加载器: why does this work?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17815236/