注释语法分析器
它是第一次,为了PHP 的世界,用 C 编写的注释解析器组件。 Phalcon\Annotations
是一个通用组件,用于在应用程序中的注释,在PHP 类中提供了方便的解析和缓存。
Annotations are read from docblocks in classes, methods and properties. An annotation can be placed at any position in the docblock:
<?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)
*/
工厂
There are many annotations adapters available (see Adapters). 您使用将取决于您的应用程序的需要。 实例化此类 adapter 的传统方法是,如下所示:
<?php
use Phalcon\Annotations\Adapter\Memory as MemoryAdapter;
$reader = new MemoryAdapter();
// .....
但是你也可以利用工厂方法来达到相同的效果:
<?php
use Phalcon\Annotations\Factory;
$options = [
'prefix' => 'annotations',
'lifetime' => '3600',
'adapter' => 'memory', // Load the Memory adapter
];
$annotations = Factory::load($options);
工厂装载机处理实例化注释适配器从配置文件时提供更大的灵活性。
读取注释
一个反射器的实现可以容易地得到,使用面向对象的接口的类上定义的注释︰
<?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 was used in the above example. 此适配器只缓存当请求正在运行时的注释,为此该适配器是更适合开发。 当应用程序在生产阶段时,有其他适配器换出。
注释类型
Annotations may have parameters or not. A parameter could be a simple literal (strings, number, boolean, null), an array, a hashed list or other annotation:
<?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([email protected](1, 2, 3))
*/
实际使用情况
下一步,我们将解释一些实际例子,关于 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
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
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
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 |
The annotations are cached only in memory. When the request ends the cache is cleaned reloading the annotations in each request. This adapter is suitable for a development stage |
Phalcon\Annotations\Adapter\Files |
Parsed and processed annotations are stored permanently in PHP files improving performance. This adapter must be used together with a bytecode cache. |
Phalcon\Annotations\Adapter\Apc |
Parsed and processed annotations are stored permanently in the APC cache improving performance. This is the faster adapter |
Phalcon\Annotations\Adapter\Xcache |
Parsed and processed annotations are stored permanently in the XCache cache improving performance. This is a fast adapter too |
执行您自己的适配器
The Phalcon\Annotations\AdapterInterface interface must be implemented in order to create your own annotations adapters or extend the existing ones.
外部资源