Кастомные аннотации в Symfony 2

    Symfony2 — это веб-фреймворк, который появился совсем недавно. Соответственно, разработчики просто не успели написать к нему стоящую документацию. В одном из текущих проектов используется MongoDB, и ACL прикрутить нему можно, нужно всего лишь написать свой ACL-провайдер. Но я решил пойти своим путём. Итак, вот что примерно у нас получится:
    class DefaultController extends Controller
    {
    
        /**
        * Dashboard page.
        * @Permissions(perm="dashboard_view")
        * @Route("/", name="ITEDashboardBundle_index")
        * @Template()
        * @return array
        */
        public function indexAction()
        {.......
    



    Как видно, здесь аннотации route и template — стандартны и я не буду о них рассказывать. Нас же интересует собственная аннотация Permissions.

    Ну что ж, приступим.
    Для начала нужно создать класс аннотаций, который будет показывать ядру, что у нас теперь есть новая аннотация:
    namespace SomeNameSpace\SomeBundle\Annotations;
    /**
    * @Annotation
    */
    class Permissions
    {
        public $perm;
    }
    

    Таким образом, аннотация будет типа @Permissions(perm=«some_value»)
    Следующим нашим шагом будет создания сервиса, в которым мы будем читать аннотации и выполнять какие-то действия, в зависимости от их значений.
    namespace SomeNamespace\SomeBundle\Annotations\Driver;
    
    use Doctrine\Common\Annotations\Reader;//Вот эта штука как раз и читает аннотации
    use Symfony\Component\HttpKernel\Event\FilterControllerEvent;//Подключаем нужный компонент ядра
    use SomeNamespace\SomeBundle\Annotations;//Юзаем свою аннотацию
    use SomeNamespace\SomeBundle\Security\Permission; //В этом классе я проверяю соответствие permission to user
    use Symfony\Component\HttpFoundation\Response; // В нашем примере я просто буду выводить 403, если нет доступа
    
    use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
    
    class AnnotationDriver{
    
        private $reader;
    
        public function __construct($reader)
        {
            $this->reader = $reader;//Получаем читалку аннотаций
        }
        /**
        * Это событие возникнет при вызове любого контроллера
        */
        public function onKernelController(FilterControllerEvent $event)
        {
    
            if (!is_array($controller = $event->getController())) { //Выходим, если нет контроллера
                return;
            }
    
            $object = new \ReflectionObject($controller[0]);// Получаем контроллер
            $method = $object->getMethod($controller[1]);// Получаем метод
    
            foreach ($this->reader->getMethodAnnotations($method) as $configuration) { //Начинаем читать аннотации
                if(isset($configuration->perm)){//Если прочитанная аннотация наша, то выполняем код ниже
                    $perm = new Permission($controller[0]->get('doctrine.odm.mongodb.document_manager'));
                    $userName = $controller[0]->get('security.context')->getToken()->getUser()->getUserName();
                    if(!$perm->isAccess($userName,$configuration->perm)){
                               //Если после проверки доступа нет, то выдаём 403
                               throw new AccessDeniedHttpException();
    
                    }
    
                 }
             }
        }
    }
    
    

    Прошу заметить, что используем мы читалку аннотаций из доктрины. Но доктрина сегодня стала неотъемлемой частью symfony2.
    Да. И последний шаг, но не менее важный. Теперь нам нужно зарегистрировать свой хук контролеера, или, если правильно назвать его: EventListener
    # SomeBundle\config\services.yml
    services:
        some_annotation_driver:
            class: SomeNamespace\SomeBundle\Annotations\Driver\AnnotationDriver #Указываем класс
            tags: [{name: kernel.event_listener, event: kernel.controller, method: onKernelController}]          #Указываем по какому событию вызывать этот сервис
            arguments: [@annotation_reader] # Передаём annotation_reader в конструктор нашего сервиса
    


    Вот, собственно, и всё! Теперь наши аннотации готовы к использованию.
    P.S. Для использования своих аннотаций в своих бандлах и контролерах нужно подключить только класс с аннотациями:
    namespace SomeNamespace\SomeBundle\Controller;
    
    use SomeNamespace\SomeBundle\Annotations\Permissions;
    
    /**
    * Dashboard controller.
    *
    * @Route("/dashboard")
    */
    class DefaultController extends Controller
    {
    
        /**
        * Dashboard page.
        * @Permissions(perm="dashboard_view")
        * @Route("/", name="ITEDashboardBundle_index")
        * @Template()
        * @return array
        */
        public function indexAction()
        {...}
    }
    

    UPD: Сделал нормальную подсветку кода, спасибо sHinE
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 34

      –6
      не удержусь… «Кастомные» — это по русски?
        +1
        Думаю, нет. Но ведь всё понятно, не так-ли?
        +11
        А вообще, меня очень печалит, что на хабре очень мало статей о Symfony 2. Ведь framework действительно стоящий, а большинство статей либо дважды два, либо просто перевод документации. Попытался просто помочь сообществу, надеюсь кому-то это нужно.
          0
          Спасибо Вам большое, недавно начал изучать Symfony2 (кстати первую версию не знаю), и любая статья на эту тему неоценима :)
            0
            Всегда рад помочь!
              0
              Гм, тоже не знаю первую версию :) начал сразу со второй.
                +1
                Не знаю, зачем они назвали новый фреймворк Symfony2, но суть в том, что он не имеет ничего общего с первой симфони. Так что, скорее всего, это плюс, что с ней незнакомы )
                  0
                  Та же идеология, тот же разработчик, то же коммюнити?
                    0
                    Возможно, разработчик тот же, но остальные два — нет
                      +1
                      Найдите мне активного члена symfony1 коммюнити, который не является членом Symfony2 коммюнити.
                      Найдите мне пункт идеологии первой симфонии, который не подойдет ко второй.
                        0
                        1. на его комментарий вы только что ответили

                        2. обратное тоже верно? если да, то полагаю, что общего меньше, чем различий.
                          0
                          1. У нас разные представления об активности :-)
                          2. Мы все еще говорим об идеологии фреймворка? Различий в чем? Вы так и не ответили на изначальный вопрос.
                            0
                            На изначальный вопрос я ответил двумя комментариями выше. Спор бессмысленный, без четкой цели и сомнительной ценности. Предлагаю прекратить.
                    0
                    Затем что symfony это довольно известный бренд. Вкладывать деньги в раскрутку нового глупо.
                0
                о, то что надо, спасибо.
                  0
                  Спасибо за статью. А вообще да, статей про вторую симфонию маловато.
                    0
                    Было бы неплохо реализовать кеширование аннотаций. А то читать их каждый раз долговато, мне кажется. Доктрина ведь их сама не кеширует?
                      +3
                      Там из коробки кэш есть в ридере (по дефолту ArrayCache). Симфони, кажется, используется по дефолту файловый кэш для аннотаций.
                        0
                        *использует
                      +1
                      «Соответственно, разработчики просто не успели написать к нему стоящую документацию.»
                      Позвольте не согласится. Нормальной документации более чем достаточно. Практических примеров использования типа Askeet or Jobeet действительно пока нет. За статью спасибо.
                        0
                        ться конечно-же.
                        0
                        Друзья, я не хочу, что бы вы здесь спорили! Я написал эту статью лишь для того, чтобы помочь сообществу. Я очень хочу, что бы Symfony была популярной среди разработчиков. И очень хочу, чтобы разработчики знали как под неё писать. Если кому-то она действительна интересна, то я могу написать ещё статей.
                          0
                          Очень даже интересна. С удовольствием почитаю.
                            0
                            Ну тогда ждите статью про расширение стандартного контроллера. А ещё, надеюсь, статью про репозитории доктрины.
                              0
                              Но последняя статья уже будет не от меня. Есть единомышленники.
                                0
                                Я могу конечно ошибаться, но все-таки выскажу свое мнение. На мой взгляд, порог входа в симфони несколько выше чем у других фреймворков. Отчасти виновата в этом документация. Не то чтобы ее было мало, просто она не так лаконична и предметна как у того же Codeigniter. Для первой версии симфони большим подспорьем было наличие практических примеров в виде аскита и джобита, в которых наглядно показаны возможности фреймворка и то, как правильно с ним работать. К чему я все это говорю?! Вы хотите популяризировать симфони, что конечно же очень хорошо. Однако темы ваших предполагаемых статей — это материал для людей, которые уже работают или работали с фреймворком. Т.е. те, кому уже популяризировать не нужно :). Мне кажется для большинства не имевших дела с с2 было бы важно узнать основы идеологии: container, di. А может быть и простой обзор компонентов, которые как известно можно использовать и отдельно от фреймворка. Как бы там ни было, решать вам, я с удовольствием почитаю ваши статьи.
                                  0
                                  основы идеологии: di, container, по-моему, уже давно должны стать основой идеологии любого фреймворка. Порог входа большой, да. Но это ничего не меняет.
                                    0
                                    хотя, можно, конечно и статьи для новичков, типа основы идеи контейнера и инъектирования зависимостей)
                                      0
                              • UFO just landed and posted this here
                                  +2
                                  Да ладно, лучше прослезитесь раз тянет :).
                                  0
                                  Аннотации более сильны, когда использовать CompilerPass и генерацию кода, вобщем, то… вот MageConf 2011 будет доклад как раз об етом.
                                    0
                                    А вам не кажется что комментарий к коду для таких аннотаций не предназначен. Не хочу пальцем показывать на какой язык я перешел но это неявное поведени совсем уж надоело. Ну раз есть возможность ретроспекции сигнатур функций то давайте кодить прямо в них, в сигнатурах. И пофиг что этого от нас никто не ожидает!

                                  Only users with full accounts can post comments. Log in, please.