繁体   English   中英

如何在Symfony中继承自定义Doctrine类注释?

[英]How to inherit custom Doctrine class annotation in Symfony?

我创建了一个自定义@TimestampAware注释,可用于在持久化或更新我的实体时自动更新时间戳属性(请参阅下面的代码)。

当直接在实体类上使用此注释时,一切正常。 但是,在基类上使用注释时,在继承的子类上无法识别。

/**
 * @TimestampAware
 */
class SomeEntity { ... }  // works fine

 /**
 * @TimestampAware
 */
class BaseEntity { ... }

class SubEntity extends BaseEntity { ... } // Annotation is not recognized

Doctrine 注释和 Annotation Reader 类的预期行为是直接在当​​前类上查找注释而不包括其父类吗? 还是我的实现有问题?

我的注释:

use Doctrine\Common\Annotations\Annotation;
use Doctrine\Common\Annotations\Reader;

/**
 * @Annotation
 * @Target("CLASS")
 */
final class TimestampAware { }

注释侦听器:

use Doctrine\Common\EventSubscriber;

class TimestampAwareSubscriber implements EventSubscriber {
    protected $reader;
    protected $logger;

    public function __construct(Reader $reader, LoggerInterface $logger) {
        $this->reader = $reader;
        $this->logger = $logger;
    }

    public function getSubscribedEvents() {
        return [
            Events::prePersist,
            Events::preUpdate,
        ];
    }

    public function prePersist(LifecycleEventArgs $args) {
        $this->onPersistOrUpdate($args);
    }    

    public function preUpdate(LifecycleEventArgs $args) {
        $this->onPersistOrUpdate($args);
    }    

    protected function onPersistOrUpdate(LifecycleEventArgs $args) {
        $this->logger->info("Reader: ".get_class($this->reader));
 
        $entity = $args->getEntity();
        $reflection = new \ReflectionClass($entity);
    
        $timestampAware = $this->reader->getClassAnnotation(
            $reflection,
            TimestampAware::class
        );
    
        if (!$timestampAware) {
            return;
        }

        // update timestamp...
    }
}

Annotation Reader 只检查相关类,它不读取父类的注释。 这可以使用如下代码轻松检查:

use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;

AnnotationRegistry::registerLoader('class_exists');

/**
 * @Annotation
 * @Target("CLASS")
 */
class Annotated {}

/**
 * @Annotated
 **/
class ParentFoo {}

class ChildFoo extends ParentFoo {}

$reader = new AnnotationReader();

$parentAnnotated = $reader->getClassAnnotation(
    new ReflectionClass(ParentFoo::class),
    Annotated::class
);

var_dump($parentAnnotated);
// Outputs `object(Annotated)#10 (0) {}`

$childAnnotated = $reader->getClassAnnotation(
    new ReflectionClass(ChildFoo::class),
    Annotated::class
);

var_dump($childAnnotated);

// outputs `null`

如果你想检查父类,你必须自己做。 ReflectionClass提供了getParentClass()方法,您可以用它来检查类层次结构。

顺便说一句,我发现这个包声称可以扩展注释,以便它们可以直接与继承一起使用。 没看好不好

除了@yivi 的精彩回答之外,我还想分享我用来解决问题的代码。 也许这有助于其他人如何遇到同样的问题:

protected function onPersistOrUpdate(LifecycleEventArgs $args) {
    $this->logger->info("Reader: ".get_class($this->reader));

    $entity = $args->getEntity();
    $reflection = new \ReflectionClass($entity);

    $timestampAware = $this->reader->getClassAnnotation(
        $reflection,
        TimestampAware::class
    );
    
    while (!$timestampAware && $reflection = $reflection->getParentClass()) {
        $timestampAware = $this->reader->getClassAnnotation(
            $reflection,
            TimestampLogAware::class
        );
    }

    if (!$timestampAware) {
        return;
    }

    // update timestamp...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM