php自动加载类实现以及解析
autoload 一般情况,我们会在autoload方法中,写很多个if else 来判断。
如何才能解耦呢,通过配置文件的形式来配置,这是我记录这代码的巧妙之处。
只是我一个同事写的代码,非常值得借鉴,记录下来,学习下。
autoload_namespaces.phpreturn [
'JadeSouth\\Service' => [
SERVICE_DIR,
],
'JadeSouth\\Model' => [
MODEL_DIR,
],
'Database' => [
CORE_DIR . 'DataBase' . DS,
],
'JadeSouth\\Document' => [
DOCUMENT_DIR,
],
'JadeSouth\\Exception' => [
EXCEPTION_DIR,
],
];
Loader.phpfinal class Loader
{
/** @var array 类全名和类文件对应映射Map */
private static $classNameToDirectoryMap = [];
/** @var array 类命名空间和类目录对应映射Map */
private static $namespacePrefixToBaseDirectoryMap = [];
/** @var array 自动加载器忽略自动加载的类全名 */
private static $missAutoloadClassNameMap = [
// 'Yar_Server',
];
/** @var array 自动加载器忽略自动加载的类命名空间 */
private static $missAutoloadNamespacePrefixMap = [];
/**
* Loader constructor. 私有化构造器,防止实例化
*/
private function __construct()
{
}
public static function registerLoader()
{
self::$classNameToDirectoryMap = require __DIR__ . DIRECTORY_SEPARATOR . 'autoload_classmap.php';
self::$namespacePrefixToBaseDirectoryMap = require __DIR__ . DIRECTORY_SEPARATOR . 'autoload_namespaces.php';
self::splAutoloadRegister();
}
private static function splAutoloadRegister()
{
spl_autoload_register('\JadeSouth\Core\Loader\Loader::loadClass', true, true);
}
public static function loadClass(string $className): bool
{
$filePath = self::findClassFilePath($className);
if (! empty($filePath)) {
self::includeFile($filePath);
return true;
}
return false;
}
/**系统加载类**/
private static function findClassFilePath(string $classFullName, string $fileExt = '.php'): string
{
//忽略掉,不加载文件
if (isset(self::$missAutoloadClassNameMap[$classFullName])) {
return '';
}
//判断文件是否存在于autoload_classmap 中是否存在,如果存在返回
if (! empty(self::$classNameToDirectoryMap[$classFullName])
&& is_file(self::$classNameToDirectoryMap[$classFullName])) {
return self::$classNameToDirectoryMap[$classFullName];
}
$classNameSubsections = explode('\\', $classFullName);
$subsectionLen = count($classNameSubsections);
$classTailNames = [];
for($i = 1; $i
//将要引入的类文件从最后一个取出来,放进第一个参数中
array_unshift($classTailNames, array_pop($classNameSubsections));
$classPrefixName = implode('\\', $classNameSubsections);
if (! empty(self::$namespacePrefixToBaseDirectoryMap[$classPrefixName])
&& ! in_array($classPrefixName, self::$missAutoloadNamespacePrefixMap)) {
foreach (self::$namespacePrefixToBaseDirectoryMap[$classPrefixName] as $item) {
$classFilePath = rtrim($item, DS) . DS . implode(DS, $classTailNames) . $fileExt;
if (is_file($classFilePath)) {
return $classFilePath;
}
}
}
}
return '';
}
private static function includeFile(string $filePath)
{
if (is_file($filePath)) {
require $filePath;
}
}
}