Парсер аннотаций
Впервые компонент парсера аннотаций написан на C для мира PHP. Phalcon\Annotations — это компонент общего назначения, который обеспечивает лёгкость парсинга и кэширования аннотаций в классах PHP для использования в приложениях.
Аннотации считываются из docblock в классах, методах и свойствах. Аннотация может быть размещена в любом месте 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()
{
// ...
}
}
Синтаксис аннотации следующий:
/** * @Annotation-Name * @Annotation-Name(param1, param2, ...) */
Также аннотация может быть размещена в любой части 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)
*/
Чтение аннотаций
Рефлектор реализован для лёгкого получения аннотаций, определённых в классе, с использованием объектно-ориентированного интерфейса:
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 был использован в приведённом выше примере. Этот адаптер кэширует аннотации только во время выполнения запроса, и поэтому он более подходит для разработки. Есть и другие адаптеры для использования в производственной среде.
Типы аннотаций
Аннотации могут иметь параметры или нет. Параметр может быть простым литералом (строки, числа, булевы значения, 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:
Включение кэша с помощью аннотаций
Предположим, мы создали следующий контроллер, и вы хотите создать плагин, который автоматически запускает кэш, если последнее выполненное действие помечено как кэшируемое. Прежде всего, мы регистрируем плагин в службе Dispatcher, чтобы уведомлять о выполнении маршрута:
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 — это плагин, который перехватывает каждое выполняемое действие в диспетчере, включая кэш при необходимости:
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);
}
}
}
Теперь мы можем использовать аннотацию в контроллере:
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, какие контроллеры относятся к административным областям:
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;
}
}
Адаптеры аннотаций
Этот компонент использует адаптеры для кэширования или не кэширования проанализированных и обработанных аннотаций, тем самым улучшая производительность или предоставляя удобства для разработки/тестирования:
| Класс | Описание |
|---|---|
| Phalcon\Annotations\Adapter\Memory | Аннотации кэшируются только в памяти. По завершении запроса кэш очищается, и аннотации загружаются заново в каждом запросе. Этот адаптер подходит для стадии разработки |
| Phalcon\Annotations\Adapter\Files | Обработанные аннотации сохраняются постоянно в файлах PHP, улучшая производительность. Этот адаптер необходимо использовать вместе с кэшем байткода. |
| Phalcon\Annotations\Adapter\Apc | Обработанные аннотации сохраняются постоянно в кэше APC, улучшая производительность. Это самый быстрый адаптер |
| Phalcon\Annotations\Adapter\Xcache | Обработанные аннотации сохраняются постоянно в кэше XCache, улучшая производительность. Это тоже быстрый адаптер |
Реализация собственных адаптеров
Для создания собственных адаптеров аннотаций или расширения существующих необходимо реализовать интерфейс Phalcon\Annotations\AdapterInterface.
Внешние ресурсы
© 2011–2017 Phalcon Framework Team
Licensed under the Creative Commons Attribution License 3.0.
https://docs.phalconphp.com/en/latest/reference/annotations.html