# 注釋解析器(Annotations Parser)
這是第一個為PHP用C語言寫的注釋解析器。`Phalcon\Annotations`是一個通用組件,為應用中的PHP類提供易于解析和緩存注釋的功能。
注釋內容是讀自類,方法和屬性的注釋區域。一個注釋單元可以放在注釋區域的任何位置。
~~~
<?php
/**
* This is the class description
*
* @AmazingClass(true)
*/
class Example
{
/**
* This a property with a special feature
*
* @SpecialFeature
*/
protected $someProperty;
/**
* This is a method
*
* @SpecialFeature
*/
public function someMethod()
{
// ...
}
}
~~~
在上面的例子中,我們發現注釋塊中除了注釋單元,還可以有注釋內容,一個注釋單元語法如下:
~~~
/**
* @Annotation-Name
* @Annotation-Name(param1, param2, ...)
*/
~~~
當然,一個注釋單元可以放在注釋內容里的任意位置:
~~~
<?php
/**
* This a property with a special feature
*
* @SpecialFeature
*
* More comments
*
* @AnotherSpecialFeature(true)
*/
~~~
這個解析器是高度靈活的,下面這樣的注釋單元是合法可解析的:
~~~
<?php
/**
* This a property with a special feature @SpecialFeature({
someParameter="the value", false
}) More comments @AnotherSpecialFeature(true) @MoreAnnotations
**/
~~~
然而,為了使代碼更容易維護和理解,我們推薦把注釋單元放在注釋塊的最后:
~~~
<?php
/**
* This a property with a special feature
* More comments
*
* @SpecialFeature({someParameter="the value", false})
* @AnotherSpecialFeature(true)
*/
~~~
## 讀取注釋(Reading Annotations)
實現反射器(Reflector)可以輕松獲取被定義在類中的注釋,使用一個面向對象的接口即可:
~~~
<?php
use Phalcon\Annotations\Adapter\Memory as MemoryAdapter;
$reader = new MemoryAdapter();
// 反射在Example類的注釋
$reflector = $reader->get("Example");
// 讀取類中注釋塊中的注釋
$annotations = $reflector->getClassAnnotations();
// 遍歷注釋
foreach ($annotations as $annotation) {
// 打印注釋名稱
echo $annotation->getName(), PHP_EOL;
// 打印注釋參數個數
echo $annotation->numberArguments(), PHP_EOL;
// 打印注釋參數
print_r($annotation->getArguments());
}
~~~
雖然這個注釋的讀取過程是非常快速的,然而,出于性能原因,我們建議使用一個適配器儲存解析后的注釋內容。 適配器把處理后的注釋內容緩存起來,避免每次讀取都需要解析一遍注釋。
[Phalcon\\Annotations\\Adapter\\Memory](http://docs.iphalcon.cn/api/Phalcon_Annotations_Adapter_Memory.html)被用在上面的例子中。這個適配器只在請求過程中緩存注釋(譯者注:請求完成后緩存將被清空),因為這個原因,這個適配器非常適合用于開發環境中。當應用跑在生產環境中還有其他適配器可以替換。
## 注釋類型(Types of Annotations)
注釋單元可以有參數也可以沒有。參數可以為簡單的文字(strings, number, boolean, null),數組,哈希列表或者其他注釋單元:
~~~
<?php
/**
* 簡單的注釋單元
*
* @SomeAnnotation
*/
/**
* 帶參數的注釋單元
*
* @SomeAnnotation("hello", "world", 1, 2, 3, false, true)
*/
/**
* 帶名稱限定參數的注釋單元
*
* @SomeAnnotation(first="hello", second="world", third=1)
* @SomeAnnotation(first: "hello", second: "world", third: 1)
*/
/**
* 數組參數
*
* @SomeAnnotation([1, 2, 3, 4])
* @SomeAnnotation({1, 2, 3, 4})
*/
/**
* 哈希列表參數
*
* @SomeAnnotation({first=1, second=2, third=3})
* @SomeAnnotation({'first'=1, 'second'=2, 'third'=3})
* @SomeAnnotation({'first': 1, 'second': 2, 'third': 3})
* @SomeAnnotation(['first': 1, 'second': 2, 'third': 3])
*/
/**
* 嵌套數組/哈希列表
*
* @SomeAnnotation({"name"="SomeName", "other"={
* "foo1": "bar1", "foo2": "bar2", {1, 2, 3},
* }})
*/
/**
* 嵌套注釋單元
*
* @SomeAnnotation(first=@AnotherAnnotation(1, 2, 3))
*/
~~~
## 實際使用(Practical Usage)
接下來我們將解釋PHP應用程序中的注釋的一些實際的例子:
### 注釋開啟緩存(Cache Enabler with Annotations)
我們假設一下,假設我們接下來的控制器和開發者想要建一個插件,如果被執行的方法被標記為可緩存的話,這個插件可以自動開啟緩存。首先,我們先注冊這個插件到Dispatcher服務中,這樣這個插件將被通知當控制器的路由被執行的時候:
~~~
<?php
use Phalcon\Mvc\Dispatcher as MvcDispatcher;
use Phalcon\Events\Manager as EventsManager;
$di["dispatcher"] = function () {
$eventsManager = new EventsManager();
// 添加插件到dispatch事件中
$eventsManager->attach(
"dispatch",
new CacheEnablerPlugin()
);
$dispatcher = new MvcDispatcher();
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
};
~~~
CacheEnablerPlugin 這個插件攔截每一個被dispatcher執行的action,檢查如果需要則啟動緩存:
~~~
<?php
use Phalcon\Events\Event;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\User\Plugin;
/**
* 為視圖啟動緩存,如果被執行的action帶有@Cache 注釋單元。
*/
class CacheEnablerPlugin extends Plugin
{
/**
* 這個事件在dispatcher中的每個路由被執行前執行
*/
public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher)
{
// 解析目前訪問的控制的方法的注釋
$annotations = $this->annotations->getMethod(
$dispatcher->getControllerClass(),
$dispatcher->getActiveMethod()
);
// 檢查是否方法中帶有注釋名稱‘Cache’的注釋單元
if ($annotations->has("Cache")) {
// 這個方法帶有‘Cache’注釋單元
$annotation = $annotations->get("Cache");
// 獲取注釋單元的‘lifetime’參數
$lifetime = $annotation->getNamedParameter("lifetime");
$options = [
"lifetime" => $lifetime,
];
// 檢查注釋單元中是否有用戶定義的‘key’參數
if ($annotation->hasNamedParameter("key")) {
$options["key"] = $annotation->getNamedParameter("key");
}
// 為當前dispatcher訪問的方法開啟cache
$this->view->cache($options);
}
}
}
~~~
現在,我們可以使用注釋單元在控制器中:
~~~
<?php
use Phalcon\Mvc\Controller;
class NewsController extends Controller
{
public function indexAction()
{
}
/**
* This is a comment
*
* @Cache(lifetime=86400)
*/
public function showAllAction()
{
$this->view->article = Articles::find();
}
/**
* This is a comment
*
* @Cache(key="my-key", lifetime=86400)
*/
public function showAction($slug)
{
$this->view->article = Articles::findFirstByTitle($slug);
}
}
~~~
### Private/Public areas with Annotations
You can use annotations to tell the ACL which controllers belong to the administrative areas:
~~~
<?php
use Phalcon\Acl;
use Phalcon\Acl\Role;
use Phalcon\Acl\Resource;
use Phalcon\Events\Event;
use Phalcon\Mvc\User\Plugin;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Acl\Adapter\Memory as AclList;
/**
* This is the security plugin which controls that users only have access to the modules they're assigned to
*/
class SecurityAnnotationsPlugin extends Plugin
{
/**
* This action is executed before execute any action in the application
*
* @param Event $event
* @param Dispatcher $dispatcher
*/
public function beforeDispatch(Event $event, Dispatcher $dispatcher)
{
// Possible controller class name
$controllerName = $dispatcher->getControllerClass();
// Possible method name
$actionName = $dispatcher->getActiveMethod();
// Get annotations in the controller class
$annotations = $this->annotations->get($controllerName);
// The controller is private?
if ($annotations->getClassAnnotations()->has("Private")) {
// Check if the session variable is active?
if (!$this->session->get("auth")) {
// The user is no logged redirect to login
$dispatcher->forward(
[
"controller" => "session",
"action" => "login",
]
);
return false;
}
}
// Continue normally
return true;
}
}
~~~
## 注釋適配器(Annotations Adapters)
這些組件利用了適配器去緩存或者不緩存已經解析和處理過的注釋內容,從而提升了性能或者為開發環境提供了開發/測試的適配器:
| Class | Description |
| --- | --- |
| [Phalcon\\Annotations\\Adapter\\Memory](http://docs.iphalcon.cn/api/Phalcon_Annotations_Adapter_Memory.html) | 這個注釋只緩存在內存中。當請求結束時緩存將被清空,每次請求都重新解析注釋內容. 這個適配器適合用于開發環境中 |
| [Phalcon\\Annotations\\Adapter\\Files](http://docs.iphalcon.cn/api/Phalcon_Annotations_Adapter_Files.html) | 已解析和已處理的注釋將被永久保存在PHP文件中提高性能。這個適配器必須和字節碼緩存一起使用。 |
| [Phalcon\\Annotations\\Adapter\\Apc](http://docs.iphalcon.cn/api/Phalcon_Annotations_Adapter_Apc.html) | 已解析和已處理的注釋將永久保存在APC緩存中提升性能。 這是一個速度非常快的適配器。 |
| [Phalcon\\Annotations\\Adapter\\Xcache](http://docs.iphalcon.cn/api/Phalcon_Annotations_Adapter_Xcache.html) | 已解析和已處理的注釋將永久保存在XCache緩存中提升性能. 這也是一個速度非常快的適配器。 |
### 自定義適配器(Implementing your own adapters)
為了建立自己的注釋適配器或者繼承一個已存在的適配器,這個[Phalcon\\Annotations\\AdapterInterface](http://docs.iphalcon.cn/api/Phalcon_Annotations_AdapterInterface.html)接口都必須實現。
## 外部資源(External Resources)
* [Tutorial: Creating a custom model’s initializer with Annotations](https://blog.phalconphp.com/post/tutorial-creating-a-custom-models-initializer)
- 簡介
- 安裝
- 安裝(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