Парсер аннотаций
Впервые компонент парсера аннотаций написан на языке C для мира PHP. Phalcon\Annotations — это компонент общего назначения, который обеспечивает удобство парсинга и кэширования аннотаций в классах PHP для использования в приложениях.
Аннотации считываются из docblocks в классах, методах и свойствах. Аннотация может быть размещена в любом месте docblock:
/**
* 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()
{
// ...
}
}
В приведенном выше примере мы находим некоторые аннотации в комментариях, аннотация имеет следующий синтаксис:
@ИмяАннотации[(параметр1, параметр2, ...)]
Также аннотация может быть размещена в любой части docblock:
/** * This a property with a special feature * * @SpecialFeature * * More comments * * @AnotherSpecialFeature(true) */
Парсер очень гибкий, следующий docblock является допустимым:
/**
* This a property with a special feature @SpecialFeature({
someParameter="the value", false
}) More comments @AnotherSpecialFeature(true) @MoreAnnotations
**/
Однако, чтобы код был более поддерживаемым и понятным, рекомендуется размещать аннотации в конце docblock:
/**
* This a property with a special feature
* More comments
*
* @SpecialFeature({someParameter="the value", false})
* @AnotherSpecialFeature(true)
*/
Чтение аннотаций
Рефлектор реализован для удобного получения аннотаций, определённых в классе, с помощью объектно-ориентированного интерфейса:
$reader = new \Phalcon\Annotations\Adapter\Memory();
//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 был использован в приведенном выше примере. Этот адаптер кэширует аннотации только во время выполнения запроса, поэтому адаптер более подходит для разработки. Существуют другие адаптеры для замены, когда приложение находится в стадии производства.
Типы аннотаций
Аннотации могут иметь параметры или нет. Параметр может быть простым литералом (строки, числа, булевы значения, null), массивом, хэшированным списком или другой аннотацией:
/**
* 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:
Включение кеша с помощью аннотаций
Предположим, у нас есть контроллер, и разработчик хочет создать плагин, который автоматически запускает кеш, если последняя выполненная операция помечена как кэшируемая. Прежде всего, мы регистрируем плагин в сервисе диспетчера, чтобы получать уведомления о выполнении маршрута:
$di['dispatcher'] = function() {
$eventsManager = new \Phalcon\Events\Manager();
//Attach the plugin to 'dispatch' events
$eventsManager->attach('dispatch', new CacheEnablerPlugin());
$dispatcher = new \Phalcon\Mvc\Dispatcher();
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
};
CacheEnablerPlugin — это плагин, который перехватывает каждую операцию, выполняемую в диспетчере, включая кеш при необходимости:
/**
* Enables the cache for a view if the latest
* executed action has the annotation @Cache
*/
class CacheEnablerPlugin extends \Phalcon\Mvc\User\Plugin
{
/**
* This event is executed before every route is executed in the dispatcher
*
*/
public function beforeExecuteRoute($event, $dispatcher)
{
//Parse the annotations in the method currently executed
$annotations = $this->annotations->getMethod(
$dispatcher->getActiveController(),
$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 = array('lifetime' => $lifetime);
//Check if there is an user defined cache key
if ($annotation->hasNamedParameter('key')) {
$options['key'] = $annotation->getNamedParameter('key');
}
//Enable the cache for the current method
$this->view->cache($options);
}
}
}
Теперь мы можем использовать аннотацию в контроллере:
class NewsController extends \Phalcon\Mvc\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);
}
}
Выбор шаблона для отображения
В этом примере мы будем использовать аннотации, чтобы указать Phalcon\Mvc\View\Simple, какой шаблон должен быть отображён после выполнения операции:
Адаптеры аннотаций
Этот компонент использует адаптеры для кэширования или не кэширования обработанных аннотаций, тем самым улучшая производительность или обеспечивая удобства для разработки/тестирования:
| Имя | Описание | API |
|---|---|---|
| Память | Аннотации кэшируются только в памяти. По окончании запроса кэш очищается, загружая аннотации заново в каждом запросе. Этот адаптер подходит для стадии разработки | Phalcon\Annotations\Adapter\Memory |
| Файлы | Обработанные аннотации хранятся постоянно в файлах PHP, улучшая производительность. Этот адаптер должен использоваться вместе с кэшем байткода. | Phalcon\Annotations\Adapter\Files |
| APC | Обработанные аннотации постоянно хранятся в кэше APC, улучшая производительность. Это самый быстрый адаптер | Phalcon\Annotations\Adapter\Apc |
| XCache | Обработанные аннотации постоянно хранятся в кэше XCache, улучшая производительность. Это тоже быстрый адаптер | Phalcon\Annotations\Adapter\Xcache |
Реализация собственных адаптеров
Интерфейс Phalcon\Annotations\AdapterInterface должен быть реализован для создания собственных адаптеров аннотаций или расширения существующих.
Внешние ресурсы
© 2011–2016 Phalcon Framework Team
Licensed under the Creative Commons Attribution License 3.0.
https://docs.phalconphp.com/en/2.0.0/reference/annotations.html