类加载器
最后更新于:2022-04-02 05:14:05
[TOC]
# 类加载器
`Phalcon\Loader` 允许您根据某些预定义规则自动加载项目类。由于此组件是用C语言编写的,因此它在读取和解释外部PHP文件时提供的开销最低。
此组件的行为基于PHP的[自动加载类](http://www.php.net/manual/en/language.oop5.autoload.php)的功能。 如果在代码的任何部分中使用了尚不存在的类,则特殊处理程序将尝试加载它。 `Phalcon\Loader` 充当此操作的特殊处理程序。 通过在需要加载的基础上加载类,整体性能得以提高,因为发生的唯一文件读取是针对所需的文件。这种技术称为[延迟初始化](http://en.wikipedia.org/wiki/Lazy_initialization)。
使用此组件,您可以从其他项目或供应商加载文件,此自动加载器符合[PSR-0](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md)和[PSR-4](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4.md)标准。
`Phalcon\Loader` 提供四种自动加载类选项。您可以一次使用一个或组合它们。
## 安全层
`Phalcon\Loader` 提供默认类名称的安全层清理,避免包含未经授权的文件。请考虑以下示例:
```php
registerNamespaces(
[
'Example\Base' => 'vendor/example/base',
'Example\Adapter' => 'vendor/example/adapter',
'Example' => 'vendor/example',
]
);
// 注册自动加载器
$loader->register();
// 所需的类将自动包含文件 vendor/example/adapter/Some.php
$some = new \Example\Adapter\Some();
```
## 注册目录
第三种选择是注册可以找到类的目录。在性能方面不建议使用此选项,因为Phalcon需要在每个文件夹上执行大量文件统计信息,查找与该类名称相同的文件。按相关顺序注册目录很重要。
```php
registerDirs(
[
'library/MyComponent',
'library/OtherComponent/Other',
'vendor/example/adapters',
'vendor/example',
]
);
// 注册自动加载器
$loader->register();
// 所需的类将自动包含它所在的第一个目录中的文件,即 library/OtherComponent/Other/Some.php
$some = new \Some();
```
## 注册类
最后一个选项是注册类名及其路径。当项目的文件夹约定不允许使用路径和类名称轻松检索文件时,此自动装带器非常有用。这是最快的自动加载方法。但是,您的应用程序越多,需要向此自动加载器添加的类/文件越多,这将有效地使类列表的维护非常麻烦,不建议这样做。
```php
registerClasses(
[
'Some' => 'library/OtherComponent/Other/Some.php',
'Example\Base' => 'vendor/example/adapters/Example/BaseClass.php',
]
);
// 注册自动加载器
$loader->register();
// 要求类将自动包含它在关联数组中引用的文件,即 library/OtherComponent/Other/Some.php
$some = new \Some();
```
## 注册文件
您还可以注册`non-classes` 的文件,因此需要一个`require`。这对于包含仅具有以下功能的文件非常有用:
```php
registerFiles(
[
'functions.php',
'arrayFunctions.php',
]
);
// 注册自动加载器
$loader->register();
```
这些文件自动加载到 `register()` 方法中。
## 其他文件扩展名
一些自动加载策略(如前缀,名称空间或目录)会自动将php扩展名附加到选中文件的末尾。如果您使用其他扩展,则可以使用方法`setExtensions`进行设置。按照定义的顺序检查文件:
```php
setExtensions(
[
'php',
'inc',
'phb',
]
);
```
## 文件检查回调
您可以通过使用`setFileCheckingCallback`方法设置不同的文件检查回调方法来加速加载器。
默认行为使用`is_file`。但是,您也可以使用`null`,在加载文件之前不会检查文件是否存在,或者您可以使用比`is_file`快得多的`stream_resolve_include_path`,但如果从文件系统中删除目标文件,则会导致问题。
```php
setFileCheckingCallback("is_file");
// Faster than `is_file()`, but implies some issues if
// the file is removed from the filesystem.
$loader->setFileCheckingCallback("stream_resolve_include_path");
// Do not check file existence.
$loader->setFileCheckingCallback(null);
```
## 修改当前策略
通过将true作为第二个参数传递,可以将其他自动加载数据添加到现有值:
```php
registerDirs(
[
'../app/library',
'../app/plugins',
],
true
);
```
## 自动加载事件
在以下示例中,`EventsManager`正在使用类加载器,允许我们获取有关操作流程的调试信息:
```php
registerNamespaces(
[
'Example\Base' => 'vendor/example/base',
'Example\Adapter' => 'vendor/example/adapter',
'Example' => 'vendor/example',
]
);
// 听取所有加载的events
$eventsManager->attach(
'loader:beforeCheckPath',
function (Event $event, Loader $loader) {
echo $loader->getCheckedPath();
}
);
$loader->setEventsManager($eventsManager);
$loader->register();
```
返回布尔值false时的某些事件可能会停止活动操作。支持以下事件:
| 事件名称 | Triggered | Can stop operation? |
| ------------------ | ------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `beforeCheckClass` | 在开始自动加载过程之前触发 | Yes |
| `pathFound` | 当加载程序找到一个类时触发 | No |
| `afterCheckClass` | 完成自动加载过程后触发。如果启动此事件,则自动装带器未找到类文件 | No |
## 故障排除
使用通用自动加载器时要记住的一些事项:
* 自动加载过程区分大小写,类将在代码中写入时加载
* 基于名称空间/前缀的策略比目录策略更快
* 如果安装了像[APC](http://php.net/manual/en/book.apc.php) 这样的缓存字节码,这将用于检索所请求的文件(执行文件的隐式缓存)
';