0

我正在尝试将 PHPCR-ODM 与现有的 Symfony 项目集成,并且无法让它(大概)检测我映射的 Document 类。具体来说,当我尝试持久化我的 MyDocument 类的 Document 时,会出现这样的错误:

[Doctrine\Common\Persistence\Mapping\MappingException]                                                                            
The class 'Example\Common\ORM\Document\MyDocument' was not found in the chain configured namespaces Doctrine\ODM\PHPCR\Document

我的类位于一个可能很奇怪的命名空间中,因为该项目也使用 Doctrine ORM,到目前为止,我刚刚为映射文档添加了一个新空间,但我无法想象命名空间名称的选择会影响功能。

根据文档,我已添加到我的 app/autoload.php:

 AnnotationRegistry::registerFile(__DIR__.'/../vendor/doctrine/phpcr-odm/lib/Doctrine/ODM/PHPCR/Mapping/Annotations/DoctrineAnnotations.php');

我的 app/config/config.yml 包括以下内容(参数在 parameters.yml 中设置):

 doctrine_phpcr:
     session:
         backend:
             type: jackrabbit
             url: %jackrabbit_url%
         workspace: %jackrabbit_workspace%
         username: %jackrabbit_user%
         password: %jackrabbit_password%
     odm:
         auto_mapping: true

我的文档类位于 src/Example/Common/ORM/Document/MyDocument.php 中,如下所示:

<?php

namespace Example\Common\ORM\Document;

use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCRODM;

/**
 * @PHPCRODM\Document
 */
class MyDocument
{
  /**
   * @PHPCRODM\Id
   */
  private $id;

  /**
   * @PHPCRODM\ParentDocument
   */
  private $parent;

  /**
   * @PHPCRODM\Nodename
   */
  private $name;

  // .. etc

最后,我用来测试集成的代码位于一个简单的控制台命令中,如下所示:

use Example\Common\ORM\Document\MyDocument;

// ...

$documentManager = $this->container->get('doctrine_phpcr.odm.default_document_manager');

$document = new MyDocument();
$document->setParent($documentManager->find(null, '/'));
$document->setName('ExampleName');

$documentManager->persist($document);
$documentManager->flush();

我已经验证我的 MyDocument 类已正确加载,但似乎没有以使 DocumentManager 意识到它是映射的 Document 类的方式处理注释。

我的猜测是我忽略了一些简单的配置步骤,但是通过反复彻底地查看 PHPCR、PHPPCR-ODM 甚至 Symfony CMF 的文档,我似乎找不到任何东西。那里的大多数示例都涉及通过 Symfony CMF 使用 PHPCR,我无法找到许多(任何?)PHPPCR-ODM 被集成到常规 Symfony 项目中的真实示例。


编辑:最终解决方案

我遵循了@WouterJ 在下面给出的建议,它解决了我的问题,我进一步遵循了他的建议,将编译器传递添加到我的 Symfony 包中,以使其使用非标准命名空间(即,除YourBundle\Document. 就我而言,这将进入一个库,该库将在其他地方而不是捆绑包中重复使用,因此它是合适的。

为此,我在src/Example/Bundle/ExampleBundle/ExampleBundle.php文件中添加了一个方法,如下所示:

<?php

namespace Example\Bundle\ExampleBundle;

use Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class ExampleBundle extends Bundle
{
  public function build(ContainerBuilder $container)
  {
    parent::build($container);

    $mappedDirectories = array(
      realpath(__DIR__ . '/../../Common/ODM/Document')
    );

    $mappedNamespaces = array(
        'Example\Common\ODM\Document'
    );

    $phpcrCompilerClass = 'Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass';
    if (class_exists($phpcrCompilerClass)) {
        $container->addCompilerPass(
            DoctrinePhpcrMappingsPass::createAnnotationMappingDriver(
              $mappedNamespaces,
              $mappedDirectories
        ));
    }
  }
}

该代码允许将任何映射的文档类放置在 Example\Common\ODM\Document 命名空间中,并且它将拾取它们。此示例使用注释,但相同的模式可用于 XML 或 YAML 映射(请参阅Doctrine\Bundle\PHPCRBundle\DependencyInjection\Compiler\DoctrinePhpcrMappingsPass方法签名的类)。

我发现我还需要定义doctrine_phpcr.odm.metadata.annotation_reader服务以使其工作,我在app/config.yml

services:
    doctrine_phpcr.odm.metadata.annotation_reader:
        class: Doctrine\Common\Annotations\AnnotationReader

可能有更好的方法来做到这一点,但这足以让它对我有用。

4

1 回答 1

1

文档应该放在包的 Document 命名空间中,而不是 ORM\Document 命名空间。

如果你真的想把它放在 ORM\Document 命名空间中(这很奇怪,因为我们说的是 ODM 而不是 ORM),你可以使用学说映射编译器通行证:http ://symfony.com/doc/当前/cookbook/doctrine/mapping_model_classes.html

于 2013-10-20T07:13:05.773 回答