类自动加载
在编写面向对象程序时,每个类新建一个PHP文件,这会带来一个烦恼:每个脚本的开头,都需要
require
一个长长的列表。这就需要一种自动加载机制。
所谓类自动加载就是当我们想使用某个命名空间下的某个类时,直接
use
某个类,然后在使用这个类时自动按照某个规则将文件require
,不用自己显示的require
相应的代码文件。我们在使用一些开源框架时,一般都引入了类自动加载。
在PHP早期版本中通过
__autoload()
函数完成自动加载,在PHP5以后,官方推荐使用spl_autoload_register()
函数实现类自动加载,spl_autoload_register()
函数可以注册任意数量的自动加载器,当使用尚未被定义的类时自动去加载。
关于类自动加载也是有一定规范的,
PSR-4
规定了类自动加载的规范。
1. psr-4
PSR-4
关于类自动加载的规范如下:
-
1.The term “class” refers to classes, interfaces, traits, and other similar structures.
-
2.A fully qualified class name has the following form:
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
1.The fully qualified class name MUST have a top-level namespace name, also known as a “vendor namespace”.
2.The fully qualified class name MAY have one or more sub-namespace names.
3.The fully qualified class name MUST have a terminating class name.
4.Underscores have no special meaning in any portion of the fully qualified class name.
5.Alphabetic characters in the fully qualified class name MAY be any combination of lower case and upper case.
6.All class names MUST be referenced in a case-sensitive fashion.
-
3.When loading a file that corresponds to a fully qualified class name …
1.A contiguous series of one or more leading namespace and sub-namespace names, not including the leading namespace separator, in the fully qualified class name (a “namespace prefix”) corresponds to at least one “base directory”.
2.The contiguous sub-namespace names after the “namespace prefix” correspond to a subdirectory within a “base directory”, in which the namespace separators represent directory separators. The subdirectory name MUST match the case of the sub-namespace names.
3.The terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.
- 4.Autoloader implementations MUST NOT throw exceptions, MUST NOT raise errors of any level, and SHOULD NOT return a value.
2. 实现
因为作者是Yii2的严重用户,所以习惯性将命名空间和目录对应,且目录全部使用小写字母,一个符合
PSR-4
规范的自动加载类如下:
/**
* Class Autoload
* @datetime 2020/6/29 11:27 上午
* @author roach
* @email jhq0113@163.com
*/
class Autoload
{
private function __construct()
{
}
private function __clone()
{
// TODO: Implement __clone() method.
}
/**
* @var array
* @datetime 2020/6/24 10:10 上午
* @author roach
* @email jhq0113@163.com
*/
private static $_namespace = [];
/**注册一个命名空间前缀
* @param string $prefix
* @param string $dir
* @datetime 2020/6/24 10:10 上午
* @author roach
* @email jhq0113@163.com
*/
public static function set($prefix, $dir)
{
self::$_namespace[ $prefix ] = $dir;
}
/**注册多个命名空间前缀
* @param array $namespaceArray
* @datetime 2020/6/24 10:14 上午
* @author roach
* @email jhq0113@163.com
*/
public static function mset($namespaceArray = [])
{
foreach ($namespaceArray as $prefix => $dir) {
self::$_namespace[ $prefix ] = $dir;
}
}
/**
* @param string $class
* @datetime 2020/6/24 10:15 上午
* @author roach
* @email jhq0113@163.com
*/
public static function autoload($class)
{
$position = strpos($class,'\\');
$prefix = substr($class, 0, $position);
if(!isset(self::$_namespace[ $prefix ])) {
return;
}
$fileName = self::$_namespace[ $prefix ].str_replace('\\','/', substr($class, $position)).'.php';
if(file_exists($fileName)) {
require $fileName;
}
}
}
在单入口应用当中,在你的入口文件
index.php
中添加如下代码即可完成自动加载。
<?php
//引入自动加载类文件
require __DIR__.'/Autoload.php';
//注册自动加载函数
spl_autoload_register('Autoload::autoload');
//注册命名空间前缀
Autoload::set('library', dirname(__DIR__).'/library');
PHP依赖管理工具
composer
会自带一个符合PSR-4
规范的类自动加载器,如果我们的项目是使用composer
管理依赖的,我们可以直接使用composer
的类自动加载器。