# 类加载器(Class Autoloader)
[Phalcon\\Loader](http://docs.iphalcon.cn/api/Phalcon_Loader.html)允许我们基于一些预定于的规则,自动的加载项目中的类。得益于该组件是C实现的,我们可以以更低的消耗去读取和解析这些外部的PHP文件。
这个组件的行为是基于PHP的[autoloading classes](http://www.php.net/manual/en/language.oop5.autoload.php)特性。如果在代码的任何地方用到了一个尚不存在的类,一个特殊的处理程序会尝试去加载它。[Phalcon\\Loader](http://docs.iphalcon.cn/api/Phalcon_Loader.html)扮演的正是这个角色。 通过按需加载的方式加载类,由于文件读取行为只在需要的时候发生,整体性能会的带提高。这个技术就是所谓的“惰性初始模式([lazy initialization](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](http://docs.iphalcon.cn/api/Phalcon_Loader.html)提供了四种类加载方式,我们可以选择其中一个或者组合起来使用。
## 安全层(Security Layer)
[Phalcon\\Loader](http://docs.iphalcon.cn/api/Phalcon_Loader.html)默认会提供一个安全层过滤类名,以避免载入一些不安全的文件。
请看下面的类子:
~~~
<?php
// Basic autoloader
spl_autoload_register(
function ($className) {
$filepath = $className . ".php";
if (file_exists($filepath)) {
require $filepath;
}
}
);
~~~
上面这个加载器缺乏任何安全措施。如果一个方法触发了加载器并且传入了一个蓄意准备的 string 作为参数,那么程序将允许执行应用可以访问的任何文件。
~~~
<?php
// This variable is not filtered and comes from an insecure source
$className = "../processes/important-process";
// Check if the class exists triggering the auto-loader
if (class_exists($className)) {
// ...
}
~~~
如果 ‘../processes/important-process.php’ 是一个有效的文件,那么外部用户可以执行未经授权的执行它。
为了避免类似的或者其他更为复杂的攻击,[Phalcon\\Loader](http://docs.iphalcon.cn/api/Phalcon_Loader.html)会移除类名中所有的不合法字符,以降低被攻击的可能。
## 注册命名空间(Registering Namespaces)
如果你的代码用命名空间组织,或者你要使用的外部类库使用了命名空间,那么`registerNamespaces()`方法提供了相应的加载机制。它接收一个关联数组作为参数,键名是命名空间的前缀,值是这些类对应的文件所在的目录。 当加载器尝试寻找文件时,命名空间的分隔符会被替换成目录分隔符。记得在路径的末尾加上斜杠。
~~~
<?php
use Phalcon\Loader;
// Creates the autoloader
$loader = new Loader();
// Register some namespaces
$loader->registerNamespaces(
[
"Example\Base" => "vendor/example/base/",
"Example\Adapter" => "vendor/example/adapter/",
"Example" => "vendor/example/",
]
);
// Register autoloader
$loader->register();
// The required class will automatically include the
// file vendor/example/adapter/Some.php
$some = new \Example\Adapter\Some();
~~~
## 注册文件夹(Registering Directories)
第三个方式是注册存放类文件的文件夹。由于性能问题这个方式并不推荐,因为Phalcon在目录里面查找跟类名同名的文件的时候,会在每个目录里面产生相当多的 file stats 操作。 请注意按照相关的顺序注册文件夹,同时,记得在每个文件夹路径末尾加上斜杠。
~~~
<?php
use Phalcon\Loader;
// Creates the autoloader
$loader = new Loader();
// Register some directories
$loader->registerDirs(
[
"library/MyComponent/",
"library/OtherComponent/Other/",
"vendor/example/adapters/",
"vendor/example/",
]
);
// Register autoloader
$loader->register();
// The required class will automatically include the file from
// the first directory where it has been located
// i.e. library/OtherComponent/Other/Some.php
$some = new \Some();
~~~
## 注册类名(Registering Classes)
最后一个方法是注册类名和它对应的文件路径。这个加载器在项目的目录结构约定上无法简单的通过路径和类名检索文件的时候相当有用。这也是最快的一种类加载方法。 然而,随着项目的增长,越来越多的 类/文件 需要加到加载器列表里,维护类列表会变的相当痛苦,因此也不推荐使用。
~~~
<?php
use Phalcon\Loader;
// Creates the autoloader
$loader = new Loader();
// Register some classes
$loader->registerClasses(
[
"Some" => "library/OtherComponent/Other/Some.php",
"Example\Base" => "vendor/example/adapters/Example/BaseClass.php",
]
);
// Register autoloader
$loader->register();
// Requiring a class will automatically include the file it references
// in the associative array
// i.e. library/OtherComponent/Other/Some.php
$some = new \Some();
~~~
## 注册文件(Registering Files)
我们还可以注册那些不是类但是需要包含到应用里面的文件。这对引用那些只有函数的文件来说比较有用。
~~~
<?php
use Phalcon\Loader;
// Creates the autoloader
$loader = new Loader();
// Register some classes
$loader->registerFiles(
[
"functions.php",
"arrayFunctions.php",
]
);
// Register autoloader
$loader->register();
~~~
这些文件文件会在`register()`被自动加载进来。
## 额外的扩展名(Additional file extensions)
上面的加载策略,包括 “prefixes”, “namespaces” or “directories” 等,会自动的在检索文件的最后面附加 “php” 后缀。如果我们使用了其他的后缀,我们可以通过 “setExtensions” 方法进行设置。文件会以我们定义的后缀顺序检索。
~~~
<?php
use Phalcon\Loader;
// Creates the autoloader
$loader = new Loader();
// Set file extensions to check
$loader->setExtensions(
[
"php",
"inc",
"phb",
]
);
~~~
## 修改当前策略(Modifying current strategies)
我们可以向加载器注册方法的第二个参数传入 “true”,来将新定义的内容附加到当前方法已定义的内容之后。
~~~
<?php
// Adding more directories
$loader->registerDirs(
[
"../app/library/",
"../app/plugins/",
],
true
);
~~~
## 自动加载事件(Autoloading Events)
在下面的例子里面,我们将事件管理器(EventsManager)和加载器一起使用,这样我们可以根据接下来的操作获取一些调试信息。
~~~
<?php
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Loader;
$eventsManager = new EventsManager();
$loader = new Loader();
$loader->registerNamespaces(
[
"Example\\Base" => "vendor/example/base/",
"Example\\Adapter" => "vendor/example/adapter/",
"Example" => "vendor/example/",
]
);
// Listen all the loader events
$eventsManager->attach(
"loader:beforeCheckPath",
function (Event $event, Loader $loader) {
echo $loader->getCheckedPath();
}
);
$loader->setEventsManager($eventsManager);
$loader->register();
~~~
下面是加载器支持的事件列表。一些事件返回 boolean false 的时候,可以终止当前活动的操作。
| 事件名称 | 触发情景 | 是否可以终止操作? |
| --- | --- | --- |
| beforeCheckClass | 在加载操作执行之前触发 | Yes |
| pathFound | 在定位到一个类文件的时候触发 | No |
| afterCheckClass | 在加载操作执行之后触发。如果这个事件触发,说明加载器没有找到所需的类文件。 | No |
## 注意事项(Troubleshooting)
在使用加载器的时候,一些关键点需要牢记于心:
* 自动加载处理过程是大小写敏感的。类文件名与代码中所写的一致。
* 基于namespaces/prefixes机制的加载策略比基于directories的要快。
* 如果安装了类似[APC](http://php.net/manual/en/book.apc.php)的缓存工具,加载器隐式的用它来缓存文件检索结果,以便提高性能。
- 简介
- 安装
- 安装(installlation)
- XAMPP下的安装
- WAMP下安装
- Nginx安装说明
- Apache安装说明
- Cherokee 安装说明
- 使用 PHP 内置 web 服务器
- Phalcon 开发工具
- Linux 系统下使用 Phalcon 开发工具
- Mac OS X 系统下使用 Phalcon 开发工具
- Windows 系统下使用 Phalcon 开发工具
- 教程
- 教程 1:让我们通过例子来学习
- 教程 2:INVO简介
- 教程 3: 保护INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程 6: Vökuró
- 教程 7:创建简单的 REST API
- 组件
- 依赖注入与服务定位器
- MVC架构
- 使用控制器
- 使用模型
- 模型关系
- 事件与事件管理器
- Behaviors
- 模型元数据
- 事务管理
- 验证数据完整性
- Workingwith Models
- Phalcon查询语言
- 缓存对象关系映射
- 对象文档映射 ODM
- 使用视图
- 视图助手
- 资源文件管理
- Volt 模版引擎
- MVC 应用
- 路由
- 调度控制器
- Micro Applications
- 使用命名空间
- 事件管理器
- Request Environmen
- 返回响应
- Cookie 管理
- 生成 URL 和 路径
- 闪存消息
- 使用 Session 存储数据
- 过滤与清理
- 上下文编码
- 验证Validation
- 表单_Forms
- 读取配置
- 分页 Pagination
- 使用缓存提高性能
- 安全
- 加密与解密 Encryption/Decryption
- 访问控制列表
- 多语言支持
- 类加载器 Class Autoloader
- 日志记录_Logging
- 注释解析器 Annotations Parser
- 命令行应用 Command Line Applications
- Images
- 队列 Queueing
- 数据库抽象层
- 国际化
- 数据库迁移
- 调试应用程序
- 单元测试
- 进阶技巧与延伸阅读
- 提高性能:下一步该做什么?
- Dependency Injection Explained
- Understanding How Phalcon Applications Work
- Api
- Abstract class Phalcon\Acl