我正在尝试将 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
可能有更好的方法来做到这一点,但这足以让它对我有用。