[TOC]
# 注解解析器
這是第一次用C語言為PHP世界編寫注解解析器組件。`Phalcon\Annotations`是一個通用組件,可以在PHP類中輕松解析和緩存注解,以便在應用程序中使用。
從類,方法和屬性中的docblock讀取注解。注解可以放在docblock中的任何位置:
```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()
{
// ...
}
}
```
注解具有以下語法:
```php
/**
* @Annotation-Name
* @Annotation-Name(param1, param2, ...)
*/
```
此外,注解可以放在docblock的任何部分:
```php
<?php
/**
* This a property with a special feature
*
* @SpecialFeature
*
* More comments
*
* @AnotherSpecialFeature(true)
*/
```
解析器非常靈活,以下docblock有效:
```php
<?php
/**
* This a property with a special feature @SpecialFeature({
someParameter='the value', false
}) More comments @AnotherSpecialFeature(true) @MoreAnnotations
**/
```
但是,為了使代碼更易于維護和理解,建議在docblock的末尾放置注解:
```php
<?php
/**
* This a property with a special feature
* More comments
*
* @SpecialFeature({someParameter='the value', false})
* @AnotherSpecialFeature(true)
*/
```
## 工廠
有許多可用的注解適配器(請參閱適配器)。您使用的那個將取決于您的應用程序的需求。實例化這種適配器的傳統方法如下:
```php
<?php
use Phalcon\Annotations\Adapter\Memory as MemoryAdapter;
$reader = new MemoryAdapter();
// .....
```
但是,您也可以使用工廠方法來實現相同的目的:
```php
<?php
use Phalcon\Annotations\Factory;
$options = [
'prefix' => 'annotations',
'lifetime' => '3600',
'adapter' => 'memory', // Load the Memory adapter
];
$annotations = Factory::load($options);
```
在處理從配置文件中實例化注解適配器時,Factory加載程序提供了更大的靈活性。
## 閱讀注解
實現反射器以使用面向對象的接口輕松獲取在類上定義的注解:
```php
<?php
use Phalcon\Annotations\Adapter\Memory as MemoryAdapter;
$reader = new MemoryAdapter();
// Reflect the annotations in the class Example
$reflector = $reader->get('Example');
// Read the annotations in the class' docblock
$annotations = $reflector->getClassAnnotations();
// Traverse the annotations
foreach ($annotations as $annotation) {
// Print the annotation name
echo $annotation->getName(), PHP_EOL;
// Print the number of arguments
echo $annotation->numberArguments(), PHP_EOL;
// Print the arguments
print_r($annotation->getArguments());
}
```
注解讀取過程非常快,但出于性能原因,建議使用適配器存儲解析的注解。適配器緩存已處理的注解,無需一次又一次地解析注解。
在上面的示例中使用了`Phalcon\Annotations\Adapter\Memory` 。此適配器僅在請求運行時緩存注解,因此適配器更適合開發。當應用程序處于生產階段時,還有其他適配器可以換出。
## 注解的類型
注解可能有參數或沒有。參數可以是簡單的文字(字符串,數字,布爾值,空),數組,散列列表或其他注解:
```php
<?php
/**
* Simple Annotation
*
* @SomeAnnotation
*/
/**
* Annotation with parameters
*
* @SomeAnnotation('hello', 'world', 1, 2, 3, false, true)
*/
/**
* Annotation with named parameters
*
* @SomeAnnotation(first='hello', second='world', third=1)
* @SomeAnnotation(first: 'hello', second: 'world', third: 1)
*/
/**
* Passing an array
*
* @SomeAnnotation([1, 2, 3, 4])
* @SomeAnnotation({1, 2, 3, 4})
*/
/**
* Passing a hash as parameter
*
* @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])
*/
/**
* Nested arrays/hashes
*
* @SomeAnnotation({'name'='SomeName', 'other'={
* 'foo1': 'bar1', 'foo2': 'bar2', {1, 2, 3},
* }})
*/
/**
* Nested Annotations
*
* @SomeAnnotation(first=@AnotherAnnotation(1, 2, 3))
*/
```
## 實際用途
接下來我們將解釋PHP應用程序中注解的一些實際示例:
### 帶注解的緩存啟動器
讓我們假設我們已經創建了以下控制器,并且您希望創建一個插件,如果執行的最后一個操作被標記為可緩存,則會自動啟動緩存。首先,我們在Dispatcher服務中注冊一個插件,以便在執行路由時得到通知:
```php
<?php
use Phalcon\Mvc\Dispatcher as MvcDispatcher;
use Phalcon\Events\Manager as EventsManager;
$di['dispatcher'] = function () {
$eventsManager = new EventsManager();
// Attach the plugin to 'dispatch' events
$eventsManager->attach(
'dispatch',
new CacheEnablerPlugin()
);
$dispatcher = new MvcDispatcher();
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
};
```
`CacheEnablerPlugin` 是一個插件,它攔截調度程序中執行的每個操作,如果需要,啟用緩存:
```php
<?php
use Phalcon\Events\Event;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\User\Plugin;
/**
* Enables the cache for a view if the latest
* executed action has the annotation @Cache
*/
class CacheEnablerPlugin extends Plugin
{
/**
* This event is executed before every route is executed in the dispatcher
*/
public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher)
{
// Parse the annotations in the method currently executed
$annotations = $this->annotations->getMethod(
$dispatcher->getControllerClass(),
$dispatcher->getActiveMethod()
);
// Check if the method has an annotation 'Cache'
if ($annotations->has('Cache')) {
// The method has the annotation 'Cache'
$annotation = $annotations->get('Cache');
// Get the lifetime
$lifetime = $annotation->getNamedParameter('lifetime');
$options = [
'lifetime' => $lifetime,
];
// Check if there is a user defined cache key
if ($annotation->hasNamedParameter('key')) {
$options['key'] = $annotation->getNamedParameter('key');
}
// Enable the cache for the current method
$this->view->cache($options);
}
}
}
```
現在,我們可以在控制器中使用注解:
```php
<?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);
}
}
```
### 帶注解的私人/公共區域
您可以使用注解告訴ACL哪些控制器屬于管理區域:
```php
<?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
*
* @return bool
*/
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;
}
}
```
## 注解適配器
該組件使用適配器來緩存或不緩存已解析和處理的注解,從而提高性能或為開發/測試提供便利:
| 類 | 描述 |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Phalcon\Annotations\Adapter\Memory` | 注解僅緩存在內存中。當請求結束時,清除緩存,重新加載每個請求中的注解。此適配器適用于開發階段 |
| `Phalcon\Annotations\Adapter\Files` | 經過解析和處理的注解將永久存儲在PHP文件中,從而提高性能。此適配器必須與字節碼緩存一起使用。 |
| `Phalcon\Annotations\Adapter\Apc` | 經過解析和處理的注解會永久存儲在APC高速緩存中,從而提高性能。這是更快的適配器 |
| `Phalcon\Annotations\Adapter\Xcache` | 經過解析和處理的注解會永久存儲在XCache緩存中,從而提高性能。這也是一個快速適配器 |
### 實現自己的適配器
必須實現`Phalcon\Annotations\AdapterInterface`接口才能創建自己的注解適配器或擴展現有注解適配器。
## 外部資源
* [教程:使用Annotations創建自定義模型的初始化程序](https://blog.phalconphp.com/post/tutorial-creating-a-custom-models-initializer)
- 常規
- Welcome
- 貢獻
- 生成回溯
- 測試重現
- 單元測試
- 入門
- 安裝
- Web服務器設置
- WAMP
- XAMPP
- 教程
- 基礎教程
- 教程:創建一個簡單的REST API
- 教程:V?kuró
- 提升性能
- 教程:INVO
- 開發環境
- Phalcon Compose (Docker)
- Nanobox
- Phalcon Box (Vagrant)
- 開發工具
- Phalcon開發者工具的安裝
- Phalcon開發者工具的使用
- 調試應用程序
- 核心
- MVC應用
- 微應用
- 創建命令行(CLI)應用程序
- 依賴注入與服務定位
- MVC架構
- 服務
- 使用緩存提高性能
- 讀取配置
- 上下文轉義
- 類加載器
- 使用命名空間
- 日志
- 隊列
- 數據庫
- 數據庫抽象層
- Phalcon查詢語言(PHQL)
- ODM(對象文檔映射器)
- 使用模型
- 模型行為
- ORM緩存
- 模型事件
- 模型元數據
- 模型關系
- 模型事務
- 驗證模型
- 數據庫遷移
- 分頁
- 前端
- Assets管理
- 閃存消息
- 表單
- 圖像
- 視圖助手(標簽)
- 使用視圖
- Volt:模板引擎
- 業務邏輯
- 訪問控制列表(ACL)
- 注解解析器
- 控制器
- 調度控制器
- 事件管理器
- 過濾與清理
- 路由
- 在session中存儲數據
- 生成URL和路徑
- 驗證
- HTTP
- Cookies管理
- 請求環境
- 返回響應
- 安全
- 加密/解密
- 安全
- 國際化
- 國際化
- 多語言支持