我目前正在 PHP 框架上进行编程(主要是出于教育原因,也是一种打发时间的方式)。我编写了一个自动加载器,它自动扫描目录树并检测其中的所有类并创建以下格式的数组:
Array(
'MyAwesomeClass' => 'path/to/file/in/some/subdirectory/MyAwesomeClass.php',
'MyOtherAwesomeClass' => 'path/to/file/MyOtherAwesomeClass.php'
// ....
);
起初这非常整洁。因为我不需要担心我把类(class)放在哪里。
但后来我发现这是非常资源密集的。所以我创建了一个缓存机制,并将索引序列化并保存到文件中。这将 PHP 脚本的响应时间减少了至少 50%。但它也带来了一些问题。
在框架中的其他类中,我经常使用以下内容:
class_exists('MyAwesomeClassController');
问题是,如果我添加新类 MyAwesomeClassController
,该类尚未在索引中,并且 class_exists
返回 false。现在的问题是,每次向框架添加新类时,我都必须删除缓存文件(以便自动加载器重新创建索引)。
我尝试过的另一件事(有点hacky):
在 Autoloader 类中,我检查是否使用 class_exists() 调用了自动加载方法。如果是这种情况,我重新创建索引以查看是否可以在某处找到请求的类。但这似乎不太有效,因为有时使用大多数不存在的类来调用 class_exists
,因此这与在每个请求上重新创建索引基本上是相同的解决方案。
有什么解决办法吗?或者我是否必须完全重写我的自动加载器?
最佳答案
我不久前就走了这条路,并得出了同样的结论:资源密集型。您实际上在这里做的是构建某种链接器。
我切换到命名空间和映射的组合。我将命名空间映射到文件夹,当调用自动加载器时,它会删除命名空间,查找相应的文件夹,并包含该文件。
我的 map 如下所示(我选择 xml 作为格式):
<?xml version="1.0" encoding="UTF-8"?>
<autoloader>
<namespace id="Ganymedes\Core">/system/core</namespace>
<namespace id="Ganymedes\Core\Debug">/system/core/debug</namespace>
</autoloader>
以及类加载器:
public function ClassLoader( $class )
{
if( class_exists( $class, false ))
return true;
$classparts = explode( '\\', $class );
$classfile = '/' . strtolower( array_pop( $classparts )) . '.php';
$namespace = implode( '\\', $classparts );
if( isset( $this->namespaces[$namespace] )) {
foreach ( $this->namespaces[$namespace] as $path )
if( is_readable( $path . $classfile ))
include_once $path . $classfile;
return true;
}
return false;
}
关于php - 自动检测类的自动加载器存在问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12859687/