简体   繁体   English

Symfony学说:向现有阅读器添加新的新注释名称空间

[英]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->NameEvent->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. UserEvent类,并在我的EventSubscriber中有一个方法,该方法创建Doctrine\\Common\\Annotations\\AnnotationReader并使用其getPropertyAnnotation($property, 'Loggable')检查非空值。

Now to the problem 现在解决问题

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类使用getClassAnnotationsgetClassAnnotation (实际上使用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.

相关问题 用于将新模型添加到基于Symfony + Doctrine构建的应用程序的标准习语 - Standard idiom for adding new models to an app built on Symfony + Doctrine 如何仅将一个文件用作Symfony 2中的Doctrine注释阅读器缓存? - How to use just one file as Doctrine annotation reader cache in Symfony 2? Doctrine (Symfony) 中的外键。 如何将新孩子绑定到已经存在的父母? - Foreign Key in Doctrine (Symfony). How do I bind a new child to an already existing parent? 找不到教义注释阅读器类 - Doctrine annotation reader class not found 不同于注释Symfony 2 / Doctrine 2 - Different in Annotation Symfony 2 / Doctrine 2 使用Symfony中的Doctrine在数据库中创建具有关系的新表 - Create a new table with a relation in the Database, with Doctrine in Symfony symfony2 doctrine2不刷新新实体 - symfony2 doctrine2 not flushing new entity 使用 Doctrine orm symfony 创建新数据库时出错 - Errors creating a new database with Doctrine orm symfony Symfony2 Doctrine2 - 通过doctrine:mapping:import从现有数据库生成多对多注释 - Symfony2 Doctrine2 - generate Many-To-Many annotation from existing database by doctrine:mapping:import Symfony2 Doctrine2-通过doctrine:mapping:import从现有数据库生成一对多注释 - Symfony2 Doctrine2 - generate One-To-Many annotation from existing database by doctrine:mapping:import
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM