[英]Symfony Doctrine: Adding new new Annotation namespaces to an existing reader
I have implemented my own Doctrine\\Common\\EventSubscriber
that subscribes to "onFlush" events and compares the EntityChangeSet to a hard coded list of class properties (like User->Name
and Event->Date
) and logs the change if necessary. 我已经实现了自己的
Doctrine\\Common\\EventSubscriber
,该订阅了“ onFlush”事件,并将EntityChangeSet与类属性的硬编码列表(如User->Name
和Event->Date
)进行比较,并在必要时记录更改。
As property names of the other classes might change, I'd much rather prefer to annotate these properties with a custom made @Loggable
. 由于其他类的属性名称可能会更改,所以我宁愿更喜欢使用定制的
@Loggable
注释这些属性。
I have built the Annotation class "Loggable", added use MyNamespace\\Annotations\\Loggable;
我建立了Annotation类“ Loggable”,添加了
use MyNamespace\\Annotations\\Loggable;
to the User
and Event
classes and have a method in my EventSubscriber that creates a Doctrine\\Common\\Annotations\\AnnotationReader
and uses its getPropertyAnnotation($property, 'Loggable')
to check for a non-null value. 到
User
和Event
类,并在我的EventSubscriber中有一个方法,该方法创建Doctrine\\Common\\Annotations\\AnnotationReader
并使用其getPropertyAnnotation($property, 'Loggable')
检查非空值。
As one could expect (or not), this particular reader throws 如人们所料(或没有料到),这个特定的读者会抛出
[Semantical Error] The annotation "@Id" in property MyNamespace\Entities\User::$id was never imported.
and is not aware of any other ORM-annotations that the reader in my EntityManager
knows about. 并且不知道我的
EntityManager
中的读者知道的任何其他ORM注释。
Do I actually have to add use Doctrine\\ORM\\Mapping as ORM;
我是否真的必须添加
use Doctrine\\ORM\\Mapping as ORM;
to every Entity class and prefix every ORM-annotation with ORM\\
just to please this newly created reader or is there a way to reuse the reader in my EntityManager
(a Doctrine\\Common\\Annotations\\SimpleAnnotationReader
by default, if I understood correctly?) 到每个 Entity类,并为每个 ORM注释加上
ORM\\
前缀, 只是为了取悦这个新创建的阅读器,或者是否有办法在我的EntityManager
重用该阅读器(如果我理解正确,默认情况下是Doctrine\\Common\\Annotations\\SimpleAnnotationReader
?)
I did my research and read through most of the answers related to Doctrine and Annotations, but I seem to be missing some conceptual understanding. 我进行了研究,并阅读了与教义和注释有关的大多数答案,但似乎缺少一些概念上的理解。 Maybe someone can point me in the right direction?
也许有人可以指出我正确的方向?
Basically, the AnnotationReader class use getClassAnnotations and getClassAnnotation (which use getClassAnnotations in fact). 基本上, AnnotationReader类使用getClassAnnotations和getClassAnnotation (实际上使用getClassAnnotations )。
getClassAnnotations: getClassAnnotations:
public function getClassAnnotations(ReflectionClass $class)
{
$this->parser->setTarget(Target::TARGET_CLASS);
$this->parser->setImports($this->getClassImports($class));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
$this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces);
return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
}
getClassAnnotation: getClassAnnotation:
public function getClassAnnotation(ReflectionClass $class, $annotationName)
{
$annotations = $this->getClassAnnotations($class);
foreach ($annotations as $annotation) {
if ($annotation instanceof $annotationName) {
return $annotation;
}
}
return null;
}
Just take a look at this line: 看看这一行:
$this->parser->setImports($this->getClassImports($class));
The annotation reader collects the use statements in order to detect any other annotation that you use. 注释阅读器收集use语句,以便检测您使用的任何其他注释。 So, about your question
所以,关于你的问题
Do I actually have to add use Doctrine\\ORM\\Mapping as ORM;
我是否真的必须添加使用Doctrine \\ ORM \\ Mapping作为ORM? to every Entity class and prefix every ORM-annotation with ORM\\ [...]?
到每个Entity类,并在每个ORM注释前加上ORM \\ [...]?
I should answer: yes, you do. 我应该回答:是的,你愿意。
Thanks to @Frank Gamess' explanations I finally managed to wade through the jungle of Doctrine's codebase and find a messy, but working solution, that doesn't involve explicit namespaces for every file. 由于@Frank Gamess的解释,我终于设法遍历了Doctrine代码库的丛林,找到了一个混乱但有效的解决方案,该解决方案并不涉及每个文件的显式命名空间。
Instead of using the simpler Setup::createAnnotationMetadataConfiguration()
when creating my EntityManager, I went a bit more verbose and performed most of the steps of the configuration myself: 在创建我的EntityManager时,没有使用更简单的
Setup::createAnnotationMetadataConfiguration()
,而是更加冗长,自己执行了配置的大多数步骤:
// preloading all of Doctrine's Annotation classes
$rc = new \ReflectionClass(Configuration::class);
$dir = dirname($rc->getFileName());
AnnotationRegistry::registerFile($dir . '/Mapping/Driver/DoctrineAnnotations.php');
// preloading my own classes
$dir = $dir ?? self::BASE_DIR . '/src/Annotations'; // BASE_DIR is my project root directory
// CustomAnnotations.php is built the same way as DoctrineAnnotations.php;
AnnotationRegistry::registerFile($dir . '/CustomAnnotations.php');
$reader = new SimpleAnnotationReader();
$reader->addNamespace('Doctrine\ORM\Mapping');
$reader->addNamespace('MyProject\Annotations');
$mapping_driver = new AnnotationDriver($reader, [self::BASE_DIR . '/src/Entities']);
$config = Setup::createConfiguration();
$config->setMetadataDriverImpl($mapping_driver);
$config->setAutoGenerateProxyClasses(true);
$EM = EntityManager::create($db_params, $config, new EventManager());
// adding the objects to my ORM-objects for later use
$this->annotation_reader = $reader;
$this->EM = $EM;
Now I can use my annotations without any use-statements or FQCN. 现在,我可以使用注释而无需任何使用声明或FQCN。 Maybe not cleaner, but less repetitive.
也许不干净,但重复性较差。
As this works, I might be able to go on to more urgent things, but if anyone can point out possibilities for refactoring, I'm all ears! 在此过程中,我也许可以继续处理更紧急的事情,但是如果有人可以指出重构的可能性,我将不知所措!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.