[Symfony] Custom Property Annotations

Salutare,

A lucrat careva dintre voi cu Custom Annotations (Doctrine) pentru atribute?

Si daca da, imi poate da un exemplu / link sau ceva?

Sunt blocat la partea de Annotation Reading, mai exact la interpretat annotation-ul.

Partea de creare e banala. Si sunt sigur ca nici asta nu e ceva super-complicat, doar ca in momentul de fata zau ca nu gasesc pe net detalii.

Merci anticipat :+1:

1 Like

Din seria “Documentatia oficiala e cea mai buna”, e explicat destul de clar aici. Iti spune de cate tipuri pot fi anotarile (3) si iti da si un exemplu despre cum sa le folosesti (destul de rudimentar, dar usor de extrapolat si pentru alte tipuri de anotari.

@cristianciofu
Pentru ca probabil ai ajuns si tu pe pagina aia, dar nu te-a ajutat prea mult o sa iti dau un exemplu complet facut de mine, in Symfony. E vorba de un listener care seteaza user-ul curent pentru o entitate nou creata, daca entitatea are ca anotare UserAware.

  1. The Annotation
    <?php
    
    namespace My\ExampleBundle\Doctrine\Annotation;
    
    
    use Doctrine\Common\Annotations\Annotation;
    
    /**
     * @Annotation
     * @Target("CLASS")
     */
    final class UserAware
    {
        public $fieldName = 'user_id';
        public $entitySetterName = 'setUser';
        public $entityGetterName = 'getUser';
    }
  1. The listener where I use the annotation (can be used in controller with a few changes)
    public function prePersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $classMetadata = $args->getEntityManager()->getClassMetadata(get_class($entity));
        /** @var \Doctrine\Common\Annotations\Reader $reader */
        $reader = $this->reader;
        /** @var \My\ExampleBundle\Doctrine\Annotation\UserAware $userAware */
        $userAware = $reader->getClassAnnotation(
            $classMetadata->getReflectionClass(),
            'My\\ExampleBundle\\Doctrine\\Annotation\\UserAware'
        );
    
        if (!$userAware) {
            return;
        }
    
        if(!$userAware->entitySetterName) {
            return;
        }
        $user = call_user_func($this->userCallable);
        $entity->{$userAware->entitySetterName}($user);
    }

Daca vrei sa accesezi reader-ul intr-un controller, poti folosi

$this->get('annotation_reader');
2 Likes

@redecs ce ai dat tu ca e exemplu e super bun, insa e un Custom Class Annotation.

E vina mea ca nu am fost mai clar : pentru Class si Method am gasit documentatii super bune, problema este insa pentru Property.

Ideea este ca eu am adaugat un listener AnnotationsListener pe care l-am definit in services :

app.annotations.listener:
    class: App\CoreBundle\Listener\AnnotationsListener
        arguments: ["@annotation_reader"]
        tags:
            - { name: kernel.event_listener, event: kernel.controller, method: onAnnotationAccess }

Dar buba e ca aici in Listener, in mai toate exemplele de pe net se extrage Controller-ul :

public function onAccessAnnotation(FilterControllerEvent $event)
{
    $controller = $event->getController();
    // ...
}

Iar eu am incercat (asa cum mi s-a parut logic) :

list($controllerObject, $methodName) = $controller;

$controllerReflectionObject = new \ReflectionObject($controllerObject);

foreach ($controllerReflectionObject->getProperties() as $reflectionProperty) {
    $annotation = $this->reader->getPropertyAnnotation($reflectionProperty, $this->annotationClass);
}

$this->annotationClass e definit cu valoarea

private $annotationClass = ‘App\CoreBundle\Annotations\MyAnnotation’;


Sperand ca va merge, insa obiectul `$annotation` e `NULL`


Am incercat tot felul de chestii gasite pe net, dar nimic nu merge...

Pare asa banal la prima privire, dar e ceva ce imi scapa :)


> Oricum, merci mult pentru comentariu si pentru incercarea de a ma ajuta

Uite ce am gasit in Doctrine\Common\Annotations\AnnotationReader (nu stiu daca asta este si implementarea de Reader pe care o folosesti si tu, trebuie sa verifici):

    public function getPropertyAnnotation(ReflectionProperty $property, $annotationName)
    {
        $annotations = $this->getPropertyAnnotations($property);

        foreach ($annotations as $annotation) {
            if ($annotation instanceof $annotationName) {
                return $annotation;
            }
        }

        return null;
    }

Ai incercat sa scrii numele classei fara dublu ? Sau sa o incarci folosind un USE statement in fisierul in care e listenerul declarat?
Deasemenea mai exista o metoda getPropertyAnnotations(ReflectionProperty $property) care iti intoarce toate anotarile de pe accea proprietate. Arunca o provire cu xdebug sau clasicul var_dump($x); die; pe acolo si vezi exact care e scaparea.

@redecs - momentan s-a renuntat la implementarea acestei mici functionalitati, urmand sa revenim la ea ceva mai tarziu (decizia sefului).

Oricum, eu cred ca o sa arunc o privire cand am timp pentru ca m-a cam enervat nebunia asta si trebuie sa o scot la capat cumva :+1:

Merci frumos