# 類加載器(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